文章目录
一、代码块
类的成员之四:代码块(初始化块)
1. 代码块概述
-
代码块的作用:用来初始化类、对象
-
代码块如果要修饰的话:只能用static修饰(其他的都不行)
-
分类:静态代码块 vs 非静态代码块
2. 静态代码块
- 内部可以有输出语句【就像方法体一样】
- 随着类的加载而执行
【不仅是像静态方法那样随着类的加载而加载,还执行了;(因为没有名字,没法由我们来调用,因此需要自动执行)】
【而且由于是静态结构,只加载一次】
【作用:可以初始化类的信息(静态属性等)】 - 一个类中可以定义多个静态代码块,类加载的时候都会执行到,执行顺序按照声明时的上下顺序依次执行
- 静态代码块的执行,优先于非静态代码块的执行【很显然,因为静态结构的加载早于非静态结构】
3. 非静态代码块:
- 内部可以有输出语句
随着对象的创建而执行
【每创建一个对象,就会执行一次】
【作用:可以在创建对象时,对对象的属性等进行初始化】 - 一个类中也可以定义多个非静态代码块,对象创建的时候都会执行到,执行顺序按照声明时的上下顺序依次执行
4. 注意点
- 虽然可以定义多个代码块,但没必要,因为代码块只能是加载类/创建对象时,统一调用,所以干脆把多个合成一个就完事了
- 代码块的作用:就是对类、对象进行初始化,因此使用频率不高,但也有用处(后面数据库连接池就用到了)
【代码块的执行,先于构造器!!!】
【类的加载,先于main()方法!!!】
(很显然,main()方法虽然是程序的入口,但本身也是一个静态方法,必须是通过类调用,只不过是虚拟机来通过类调用的,而非我们自己;既然是通过类调用的,显然必须先加载类)
二、内部类
类的内部成员之五:内部类
1. 内部类概述
【有些时候,在一个类当中,某个成分作为属性出现难以表明其细节,在类外单独定义一个类又没必要(因为只有本类使用),这种时候就适合把这个成分单独定义成一个结构,即"内部类"(本身是一个类,能定义属性、方法、构造器,同时又是外部类的一个属性)】
- Java中允许将一个类A声明在另一个类B中,则类A就是"内部类",类B则称为"外部类"
- 内部类的分类:成员内部类(静态、非静态) vs 局部内部类(方法内、代码块内、构造器内)
【像变量一样,分为成员变量和局部变量】
2. 成员内部类
2.1 一方面,作为外部类的成员:
- 可以调用外部类的结构
- 可以被static修饰
- 可以使用全部的4种权限修饰符
【正常一个类不能用static修饰,只能使用两种权限修饰符】
2.2 另一方面,作为一个类:
- 类内可以定义属性、方法、构造器等
- 可以被final修饰,表示此类不能被继承(言外之意,不用final修饰,此类就可以被继承)
- 可以被abstract修饰
3. 内部类主要只需关注如下3个问题:
4.1 如何实例化成员内部类的对象
//创建静态的成员内部类的实例
Person.Dog dog = new Person.Dog();
//创建非静态的成员内部类的实例
Person p = new Person();
Person.Bird bird = p.new Bird(); //(非静态结构,都要通过对象来调用)
4.2 如何在成员内部类中区分调用外部类的结构
【尤其是重名的时候】
public void display(String name){
System.out.println(name); //方法的形参
System.out.println(this.name); //内部类Bird的属性
System.out.println(Person.this.name); //外部类Person的属性
getComparable(); //对于外部类中不重名结构,可以直接调用,前面省Person.this【注意:不是this,此时this指代的是内部类本身,而非外部类】
}
4.3 开发中局部内部类的使用
//局部内部类的常见用法:希望调用方法的时候,完成一个实现了某个接口的"实现类",同时帮我造个该实现类的对象,并返回给我
//例如:返回一个实现了Comparable接口的类的对象
public Comparable getComparable(){
//创建一个实现了Comparable接口的类:局部内部类【为什么不把这个方法放在外面?因为外面用不到】
//方式一:
class MyComparable implements Comparable{
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
}
return new MyComparable();
}
【内部类:同时满足 类 & 类的成员 的一切要求,(前面讲过的内容全部适用,比如:静态内部类中,不能调用外部类的非静态结构)】
代码实例:
//测试
public class InnerClassTest {
public static void main(String[] args) {
//1. 关注问题1:如何实例化成员内部类的对象
//创建Dog实例(静态的成员内部类)
Person.Dog dog = new Person.Dog();
//创建Bird实例(非静态的成员内部类)
Person p = new Person();
Person.Bird bird = p.new Bird(); //(非静态结构,都要通过对象来调用)
bird.display("黄鹂");
}
}
//这里只是举例来测试内部类的使用规则,(实际上Dog、Bird在Person里显然不合理)
class Person{
String name = "小明";
int age;
//静态内部类
static class Dog{
public void print(){
System.out.println("我是一只汪汪汪");
}
}
//非静态成员内部类
class Bird{
String name = "喜鹊";
public void sing(){
System.out.println("我是一只小小鸟");
}
public void display(String name){
//2. 关注问题2:如何在成员内部类中区分调用外部类的结构
System.out.println(name); //方法的形参
System.out.println(this.name); //内部类Bird的属性
System.out.println(Person.this.name); //外部类Person的属性
getComparable(); //对于外部类中不重名结构,可以直接调用,前面省略Person.this【注意:不是this,此时this指代的是内部类本身,而非外部类】
}
}
//3. 关注点3:开发中局部内部类的使用
//局部内部类的常见用法:希望调用方法的时候,完成一个实现了某个接口的"实现类",同时帮我造个该实现类的对象,并返回给我
//例如:返回一个实现了Comparable接口的类的对象
public Comparable getComparable(){
//创建一个实现了Comparable接口的类:局部内部类【为什么不把这个方法放在外面?因为外面用不到】
//方式一:
// class MyComparable implements Comparable{
// @Override
// public int compareTo(Object o) {
// // TODO Auto-generated method stub
// return 0;
// }
// }
//
// return new MyComparable();
//方式二:匿名类对象
return new Comparable() {
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
};
}
}
4. 注意:内部类也会生成字节码文件

4.1 局部内部类的小注意点
在局部内部类的方法中(比如:onClick())如果调用局部内部类所声明在的方法(比如:onCreate())中的局部变量(比如:number),要求此局部变量是final的
-
【因为外部类、内部类都会生成对应的字节码文件,从作用域的角度讲,内部类中的方法自然可以调用外部类中的局部变量;但从文件的角度讲,显然是两个字节码文件,跨文件了,所以实际上相当于是把number的一个副本给了内部类让其使用,既然是副本,自然不允许修改(因为改了也没用,又不是把本身传了过来)】
-
【这一要求的应用在移动端开发(Android)中很常见】
-
JDK7.0及以前版本,要求显式声明此局部变量为final
-
JDK8.0以后,可以省略final的声明(一旦调用,默认会给加上)
public class InnerClassTest {
//仅作举例说明(模仿安卓开发中的方法)
public void onCreate(){
int number = 10;
//这里new的就是一个匿名内部类的匿名对象
button.setOnClickListener(new View.onClickListener(){
public void onClick(){
System.out.println("Hello");
System.out.println(number); //调用内部类所在方法中的局部变量
}
});
}
}
本文详细介绍了Java中的代码块和内部类。代码块分为静态和非静态,用于初始化类和对象,静态代码块在类加载时执行,非静态代码块在对象创建时执行。内部类作为类的成员,可以是静态或非静态,可以拥有自己的属性和方法,且可以访问外部类的结构。成员内部类和局部内部类在实例化和使用上有所不同,内部类会生成单独的字节码文件。在局部内部类中使用外部方法的局部变量需为final类型。

5154

被折叠的 条评论
为什么被折叠?



