Java面向对象

##什么是面向对象?

面向对象是相对面向过程而言,与面向过程一样,都是一种思想。

面向过程以函数为基础,关注实现过程,强调功能行为;

面向对象以对象为基础,关注实现结果,将功能封装近对象,强调具备了功能的对象。

面向对象是基于面向过程的。

##类和对象的关系

java中描述事物通过类的形式体现,是一个抽象的概念。

对象即是该类事物实实在在存在的个体。

类是一组相同属性行为的对象的抽象。

举例:

类 :手机

对象:Nokia,Moto,HTC

##类有哪些内容组成?

描述任意一类事物就是在描述他的属性和行为。

Java中的类class由成员变量成员方法两部分组成,分别对应一类事物的属性和行为。
定义类其实也就是定义类中的成员(成员变量和成员方法)。

1
2
3
4
5
6
7
8
9
10
11
12
//定义一个类
class Phone{
//成员变量(属性)
String color = "white";
String brand = "Nokia";
int price = 998;

//成员方法()
public void createPhone(){
System.out.println(color + brand + price);
}
}

##变量使用原则

就近原则

##如何创建对象?

java中通过new关键字来创建实体。实体其实就是用来封装具体数据用的,如数组。对象也是同样道理,使用new关键字来创建对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//创建一个对象
class Phone{
String color = "white";
String brand = "Nokia";
int price = 998;

public void createPhone(){
System.out.println(color + brand + price);
}
}

class PhoneDemo{
public static void main(String args){
Phone p = new Phone();//创建对象
p.color = "black";//修改对象的属性
p.createPhone();//使用对象的功能,即调用类中的方法
}
}

##成员变量与局部变量有什么区别?

作用范围

成员变量:定义在类中,可以被类中的任意方法访问。

局部变量:只在它所属的局部大括号中有效。

存储情况

成员变量(非静态):存储在堆内存中,随着对象的存在而存在。当对象变成垃圾被回收时,该该对象中的成员变量会消失。

成员变量(静态):存储在方法区中,随着的加载而加载,随着类的消失而消失。

局部变量:存储在栈内存中,当方法被调用,或者语句被执行的时候,才存在。

当方法运行完毕,或者语句运行完毕时,局部会被自动释放。所以成员变量也称之为实例(对象)变量。

初始化情况

成员变量:在堆内存中有默认初始化值。

局部变量:必须手动初始化后,才可以被使用。

##匿名对象

匿名对象是对象的简化形式,是没有名字的对象。

匿名对象的使用注意事项:

当对对象方法仅进行一次调用的时候使用;

匿名对象可以作为实际参数进行传递。

##封装(Encapsulation)

隐藏对象的属性和实现细节,仅对外提供公共访问方式。

封装的好处

  • 将变化隔离。
  • 便于使用。
  • 提高重用性。
  • 提高安全性。

原则

将不需要对外提供的内容都隐藏起来。
把属性都隐藏,提供公共方法对其访问。

##private(私有)关键字

概念

  1. 权限修饰符。
  2. 用于修饰成员(成员变量和成员方法)
  3. 被私有化的成员只在本类中有效。
  4. 当成员私有后,提高了安全性。但是访问权限降低了。这时可以通过对外提供公有方法的形式对其进行访问。

好处:

可以在方法中对成员变量的访问进行控制。

常用场景

将成员变量私有化,对外提供对应的set ,get方法对其进行访问。提高对数据访问的安全性。

1
2
void setAge(int a){}
int getAge()

##构造方法

构造方法的特点

构造方法的方法名必须与类名相同。

构造方法没有返回类型,也不能定义为void,在方法名前面不声明方法类型。

构造方法不能由编程人员调用,而要系统调用。

一个类可以定义多个构造方法,也就是构造方法可以重载,以参数的个数,类型,或排列顺序区分。

构造方法细节

如果在定义类时没有定义构造方法,则编译系统会自动插入一个无参数的默认构造器,这个构造器不执行任何代码。

作用

构造方法的主要作用是完成对象的初始化工作,它能够把定义对象时的参数传给对象的域。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//无参构造方法调用有参构造方法

class Test{
public static void main(String args){
Phone p = new Phone();
}
}

class Phone{
private String brand;
Phone(){//无参构造方法
this(""); //必须放在第一行,而且不能直接用this(brand)
System.out.println("这是个无参构造方法。");
}

Phone(String brand){//有参构造方法
this.brand = brand;
}
}

构造方法和一般方法的区别

功能上的区别:

  • 构造方法是给对象初始化的
  • 一般方法是因为对象需要满足某种功能定义的

执行上的区别:

  • 构造方法,是对象创建的时候被执行,不用调用。
  • 一般方法是什么时候调用,就什么时候执行,不调用就永远不执行。

书写上的区别:

  • 构造方法,是不需要有返回值,包括void,但是可以有return关键字来结束。
  • 一般方法是必须具备返回值

构造代码块

构造代码块又叫初始化块,在创建对象时执行,构造代码块是对构造方法的补充,不接收任何参数,定义一些所有对象共有的属性和方法时就可以用构造代码块。

特点

  1. 构造代码块在类中方法外;
  2. 构造代码块没有名字,只能在创建对象的时候被自动调用;
  3. 如果有多个构造代码块,那么创建对象时就按照构造代码块的源码顺序,依次执行,构造代码块全部执行完成后,再执行构造方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//构造代码块
class Person {
public Person(){
System.out.println("我是构造方法");
}
public Person(int a){
System.out.println("这是构造方法1");
}
{
for(int a = 1;a <= 10;a++){
System.out.println("Hello Java!");
}//定义对象共有的属性和方法,提高代码的复用性和整个应用的可维护性。
System.out.println("这是构造代码块2");
}

##对象初始化过程

加载main方法所在的类和对象类进方法区→执行静态代码块→主方法进栈→在栈内存中开辟一个变量空间→在堆内存中开辟内存空间new一个对象→给对象一个内存地址值→对成员变量进行默认初始化→对成员变量进程显式初始化→构造代码块对成员变量初始化→构造方法对变量初始化→把地址值赋给栈内存中的变量空间

##代码执行顺序

静态代码块→构造代码块→构造方法
静态成员随类的加载而加载,类只加载一次,因此静态代码块也只执行一次。

##this关键字

this是一个关键字。代表当前对象的引用。

哪个对象调用this所在的方法,this就代表哪个对象。

使用场景

当局部变量和成员变量一样的时候,使用this关键字可以解决局部变量隐藏成员变量问题;

1
2
3
4
5
6
7
8
9
class Phone{
String color;
String brand;

public void show(String color,String brand){
this.color = color;
this.brand = brand;//this.成员变量名
}
}

在成员方法中调用其他成员方法,如果不加,默认也有this;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Phone{
String color;
String brand;

public void setColor(String color){
this.color = color;
}
public String getColor(){
return color;
}

public void show(){
System.out.println(this.getColor());//在成员方法中调用其他成员方法
}
}

在构造方法中调用其他的构造方法,用法是“this(参数列表)”,只能用在类的构造方法中,而且只能放在构造方法的第一行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Phone{
String color;
String brand;

public Phone(){}

public Phone(String color){
this.color = color;
}

public Phone(String color,String brand){
this("yellow"); //调用Phone(String color)这个构造方法,放在第一行
this.brand = brand;
}
}

##Static关键字

static是一个修饰符,用于修饰成员(成员变量和成员方法)。

当成员被静态修饰后,就多了一种被调用方式,不仅可以被对象调用,也可以被类名调用,格式是:类名.静态成员。

static特点

  1. 随着类的加载而加载。也就是说:静态会随着类的消失而消失,说明它生命周期最长。
  2. 优先于对象存在。因为静态随类的加载而加载,因此一定是静态先存在,对象后存在。
  3. 被所有对象共享。对对象的共享数据在方法区提供单独的存储空间,节省内存。
  4. 可以被类名所调用。无需在堆中创建对象即可被调用。

非静态的成员变量又叫实例变量,静态变量又叫类变量

非静态的成员变量(实例变量)与静态变量(类变量)的区别

内存中的位置:

  • (类变量)静态变量随着类的加载而存在于方法区中;
  • 实例变量随着对象的建立而存在于堆内存中。

生命周期

  • 静态变量的生命周期最长,随着的消失而消失;
  • 实例变量的生命周期随着对象的消失而消失。

所属

静态变量也称之为类变量,所属于整个,被整个类的对象所共享;
实例变量是对象的特有数据,所属于对象

静态使用注意事项

静态方法访问有局限性,只能访问静态成员,不能访问非静态成员。

  • 非静态方法既可以访问静态也可以访问非静态;
  • 非静态方法中不可以定义静态变量,因为静态随类加载而加载,优于对象存在的。

静态方法中不可以定义thissuper关键字。

  • 因为静态优先于对象存在。所以静态方法中不可以出现this。

主函数是静态的

1
2
3
4
5
6
7
8
9
10
//主函数举例
class StaticMain {
static int x = 4;
public static void main(String[] args) {
method();//主函数是静态的,要调用method方法,则method方法也必须是静态的。
}
public static void method(){
System.out.println(x);//method方法是静态的,因此使用的变量x也必须是静态的。
}
}

静态代码块

随着类的加载而执行,只执行一次并优先于主函数。 用于给类进行初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
执行顺序:静态代码块→构造代码块→构造方法
*/

class Person {
{
System.out.println("这是构造代码块");
}
public Person(){
System.out.println("这是构造方法");
}
static{
System.out.println("这是静态代码块");
}

}
class StaticDemo4 {
public static void main(String[] args) {
new Person();
new Person();//多次调用对象,只执行一次静态代码块。
}
}

局部代码块&构造代码块&静态代码块

局部代码块

  • 作用:控制变量的生命周期;
  • 在程序中,当我们已经使用完x后,并且在接下来的代码中,不会再用到x,那么就没必要让x在内存中占用空间了,这用情况下,可以使用局部代码块,将x及其所设计到的区域封装为局部代码块,他们在程序执行中顺序不变,只是在执行完成后消失。

构造代码块

  • 作用:存在于类中,它可以给所有对象进行初始化;
  • 当类中的构造方法以重载的形式存在时,并且有共同成员变量或共同的方法时,可以通过构造代码块对其进行初始化;这样可以减少代码的重复。

静态代码块

  • 作用:加载驱动器;
  • 当类中的方法都被静态了化,并且构造方法被private了,这时我们不能再将这个类实例化,然而又想让类增加一些属性,就可以使用静态代码块。

##给成员变量赋值的方式有几种?分别怎么实现?

  1. 在类中显式初始化时给成员变量赋值;
  2. 非静态的成员方法调用成员变量时给成员变量赋值;
  3. 构造方法里调用成员变量赋值;
  4. 创建对象时调用构造方法时给成员变量赋值;
  5. 类调用静态成员变量时可以给静态成员变量赋值。