Java | 类的五大成员
LI SIR Lv4

类的五大成员:属性、方法、构造器、代码块、内部类。


属性

属性也称为成员变量。

  • 声明属性的语法格式:[修饰符] 数据类型 属性名;

  • 在其他类中属性的赋值:对象.属性名 = 值;

  • 声明属性的位置:必须在类中,其他成员(方法、构造器等)的外面。

属性的特点

  • 属性有默认值。

  • 每一个对象的属性是独立的。

属性的默认值

基本数据类型:

  • byte, short, int, long 默认值为 0

  • float, double 默认值为 0.0

  • char 默认值为 \u0000

  • boolean 默认值为 false

引用数据类型:

  • 类、数组、接口默认值为 null

变量的分类

按照变量声明的“位置”分为可分为:

  • 局部变量

  • 成员变量

    • 实例变量:没有 static 修饰的属性。

    • 类变量:使用 static 修饰的属性。

局部变量

  • 局部变量的声明的位置:方法的形参列表、方法体、代码块中。

  • 局部变量的初始化:形参的初始化,必须在调用时,由实参赋值;其他的局部变量,必须手动初始化。

  • 局部变量存放位置:栈。

  • 局部变量的生命周期:当代码执行到局部变量的声明处开始,到它的作用域结束而结束。

  • 局部变量可用的修饰符:final。

成员变量

  • 成员变量的声明的位置:类中、方法和代码块等外面。

  • 成员变量的初始化:有默认值。可以显式初始化、使用构造器初始化,或者定义 set 方法可以再次修改值。

  • 成员变量存放位置:实例变量存放在堆中;类变量存放在方法区中。

  • 成员变量的生命周期:随着对象的创建而创建,随着对象被垃圾回收而消亡。每一个对象的成员变量是独立的。

  • 成员变量可用的修饰符:访问修饰符(private,默认,protected,public)、static、final、volatile 等。

方法

方法(method),又称为函数(function),代表的是一个独立的功能。例如:

  • Math.sqrt(m) 这个 sqrt(m) 方法,返回 m 的平方根。

  • System.out.println() 这个 println() 方法打印 () 中的内容。

把代码封装到一个方法中的目的,简单的实现功能的复用。

方法的要求和特点

  • 必须先声明后使用。

  • 不调用不执行,调用一次执行一次。

  • 调用时必须遵循一定的格式。

  • 方法声明的位置必须在类中,并且在方法外。

方法的参数传递机制

  • 当形参的数据类型是基本数据类型时,实参给形参传递的是“数据值”,“形参”是“实参”的一个“副本”,对形参的修改不会影响实参。主方法和你所定义的方法在内存中是两个互相独立的空间,当你调用自己定义的方法执行完之后,它就会撤掉,变成垃圾准备回收了。

  • 当形参的数据类型是引用数据类型时,实参给形参传递的是“地址值”,意味着“形参”和“实参”同时指向同一个对象,那么“形参”修改了它的属性,也意味着“实参”的属性也被修改了。

方法的重载

在同一个类中,出现了两个或多个“方法名称相同”、“形参列表不同”的方法,这些方法我们称为“方法的重载”,和返回值类型无关。

形参列表不同:个数、数据类型不同。

构造器

构造器,又称为构造方法,构造器可以在创建对象的同时,为属性初始化,或赋初始值。

构造器的特点

  • 所有的类都有构造器。

  • 构造器可以重载。

  • 如果没有声明构造器,那么编译器将会自动生成一个默认的无参构造器。

  • 如果手动声明了构造器,那么编译器就不会再自动生成无参构造了,如果你还需要无参构造,那么必须自己定义。

  • 构造器的名称必须与类名相同,并且没有返回值类型,也不需要写 void。

代码块

代码块的作用:为属性初始化。

代码块分为以下两种:

  • 静态代码块:为静态属性初始化,或者说辅助类初始化。

  • 非静态代码块:为非静态属性初始化,或者说辅助实例(对象)初始化。

代码块执行

  • 静态代码块:在类初始化时执行,只执行一次。

  • 非静态代码块:在实例初始化时执行,创建一个对象,执行一次。

类初始化

每一个类,编译器会自动生成一个 clinit(),称为类初始化方法。子类初始化时,如果父类没有初始化,会先初始化父类。

这个方法的方法体由以下两部分组成:

  1. 静态变量的显式赋值语句。

  2. 静态代码块中的语句。

这两个部分,谁在上面谁先执行。

实例初始化

每一个构造器,编译器会自动生成一个对应的 init(),称为实例初始化方法。创建子类对象时,也会导致父类的实例初始化方法执行。

这个方法的方法体由以下三部分组成:

  1. 非静态变量的显式赋值语句。

  2. 非静态代码块中的语句。

  3. 对应构造器的语句。

第一部分和第二部分仍然是谁在上面谁先执行,构造器永远是最后执行。

初始化顺序

父类初始化 clinit >>> 子类初始化 clinit >>> 父类的实例初始化 init >>> 子类的实例初始化 init

一开始都是静态的先初始化。

内部类

一个类的内部又完整的嵌套了另外一个类结构。被嵌套的类称为内部类,嵌套其他类的类称为外部类。内部类是类的五大成员之一,其最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系。

内部类的分类

定义在外部类的局部位置上:

  • 局部内部类

  • 匿名内部类

定义在外部类的成员位置上:

  • 成员内部类

  • 静态内部类

局部内部类

局部内部类是定义在外部类的局部位置,比如方法体、代码块中,并且有类名。

1
2
3
4
5
6
7
8
9
class OuterClass { // 外部类
// ...
public void method() {
// ...
class InnerClass { // 局部内部类
// ...
}
}
}

特点:

  • 可以直接访问外部类的所有成员,包含私有的。

  • 不能添加访问修饰符,但可以使用非访问修饰符 final 来修饰。

  • 如果外部类和局部内部类的成员重名时,默认遵循就近原则。

作用域:

  • 仅在定义它的方法体或代码块中。

成员的访问方法:

  • 局部内部类访问外部类的成员:直接访问。如果成员重名,需要用<外部类类名>.this.<成员名>去访问。

  • 只能在其作用域中访问局部内部类的成员和创建局部内部类的对象。

匿名内部类

局部内部类是定义在外部类的局部位置,比如方法体、代码块中,并且没有类名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
interface Product { // 接口
// ...
void show();
}

public class Main {
public static void main(String[] args) {
// ...
m1(new Product() { // 匿名内部类
@Override
public void show() {
// ...
}
});
}

public static void m1(Product product) {
// ...
product.show();
}
}

特点:

  • 没有名字,不能有构造方法。

  • 匿名内部类可以当作实参直接传递。

  • 匿名内部类使用单独的块表示初始化块

  • 匿名内部类是与继承或实现合并在一起的没有名字的内部类。

  • 匿名内部类不利于代码的重用,一般在确定此内部类只会使用一次时,才会使用匿名内部类。

语法格式:

1
2
3
new 实现接口() {
//匿名内部类类体部分
}
1
2
3
new 父类构造器(实参列表) {
//匿名内部类类体部分
}

这两种格式分别对应两种实现,一种是接口的实现,另一种是抽象类的实现。对于实现接口,由于接口是没有构造函数的,所以实参列表一定是空的。

成员内部类

成员内部类是定义在外部类的成员位置,并且没有 static 修饰。

1
2
3
4
5
6
7
8
9
10
class OuterClass { // 外部类
// ...
public void method() {
// ...
}

class InnerClass { // 成员内部类
// ...
}
}

特点:

  • 可以直接访问外部类的所有成员,包含私有的。

  • 可以添加任意访问修饰符。

  • 如果外部类和成员内部类的成员重名时,默认遵循就近原则。

作用域:

  • 和外部类的其他成员一样,为整个类体。

成员的访问方法:

  • 成员内部类访问外部类的成员:直接访问。如果成员重名,需要用<外部类类名>.this.<成员名>去访问。

  • 外部类访问成员内部类的成员:先创建成员内部类对象,再访问。

在外部其他类创建成员内部类对象的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 第一种方法
*/

public class Main {
public static void main(String[] args) {
// 创建外部类对象
OuterClass outerClass = new OuterClass();
// 使用外部类对象创建一个成员内部类对象
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
}
}

class OuterClass { // 外部类
// ...
public void method() {
// ...
}

class InnerClass { // 成员内部类
// ...
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 第二种方法
*/

public class Main {
public static void main(String[] args) {
// 创建外部类对象
OuterClass outerClass = new OuterClass();
// 调用外部类的 getInnerClass 方法获取成员内部类对象
OuterClass.InnerClass innerClass = outerClass.getInnerClass();
}
}

class OuterClass { // 外部类
// ...
public void method() {
// ...
}

class InnerClass { // 成员内部类
// ...
}

public InnerClass getInnerClass() {
return new InnerClass(); // 返回成员内部类对象
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 第三种方法
*/

public class Main {
public static void main(String[] args) {
// 创建外部类匿名对象,紧接着创建成员内部类对象,其本质和第一种方法一样,但这样更加简洁
OuterClass.InnerClass innerClass = new OuterClass().new InnerClass();
}
}

class OuterClass { // 外部类
// ...
public void method() {
// ...
}

class InnerClass { // 成员内部类
// ...
}
}

静态内部类

静态内部类是定义在外部类的成员位置,并且有 static 修饰。

1
2
3
4
5
6
7
8
9
10
class OuterClass { // 外部类
// ...
public void method() {
// ...
}

static class InnerClass { // 静态内部类
// ...
}
}

特点:

  • 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员。

  • 可以添加任意访问修饰符。

  • 如果外部类和静态内部类的成员重名时,静态内部类访问时,默认遵循就近原则。

作用域:

  • 和外部类的其他成员一样,为整个类体。

成员的访问方法:

  • 静态内部类访问外部类的成员:直接访问所有静态成员。如果成员重名,需要用<外部类类名>.<静态成员名>去访问。

  • 外部类访问静态内部类的成员:先创建静态内部类对象,再访问。

在外部其他类创建静态内部类对象的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 第一种方法
*/

public class Main {
public static void main(String[] args) {
// 无需创建外部类对象,直接通过 <外部类类名>.<静态内部类类名> 创建
OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
}
}

class OuterClass { // 外部类
// ...
public void method() {
// ...
}

static class InnerClass { // 静态内部类
// ...
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 第二种方法
*/

public class Main {
public static void main(String[] args) {
// 调用外部类的 getInnerClass 静态方法获取静态内部类对象
OuterClass.InnerClass innerClass = OuterClass.getInnerClass();
}
}

class OuterClass { // 外部类
// ...
public void method() {
// ...
}

static class InnerClass { // 静态内部类
// ...
}

public static InnerClass getInnerClass() {
return new InnerClass(); // 返回静态内部类对象
}
}
 评论
评论插件加载失败
正在加载评论插件
总字数 116.8k 访客数 访问量