面向对象之类的成员:代码块、内部类

类的成员之四:代码块

(重要性相较于属性、方法、构造器差一些)

作用

用来初始化 类、对象 的信息

分类(是否有static修饰)

静态代码块

  1. 内部可以输出语句
  2. 随着类的加载而执行,而且只执行一次
  3. 如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
  4. 静态代码块的执行要优先于非静态代码块的执行
  5. 静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构

非静态代码块

  1. 内部可以输出语句
  2. 随着对象的创建而执行
  3. 每创建一个对象,就执行一次非静态代码块
  4. 作用:可以在创建对象时,对 对象的属性 等进行初始化(再赋值)
  5. 如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
  6. 非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法(全都可以调用)

练习

​ 实例化子类对象时,涉及到父类、子类中静态代码块、非静态代码块、构造器的加载顺序:
总结:由父及子,静态先行。

//LeafTest.java
class Root{
	static{
		System.out.println("Root的静态初始化块");
	}
	{
		System.out.println("Root的普通初始化块");
	}
	public Root(){
		System.out.println("Root的无参数的构造器");
	}
}
class Mid extends Root{
	static{
		System.out.println("Mid的静态初始化块");
	}
	{
		System.out.println("Mid的普通初始化块");
	}
	public Mid(){
        //super();
		System.out.println("Mid的无参数的构造器");
	}
	public Mid(String msg){
		//通过this调用同一类中重载的构造器
		this();
		System.out.println("Mid的带参数构造器,其参数值:"
			+ msg);
	}
}
class Leaf extends Mid{
	static{
		System.out.println("Leaf的静态初始化块");
	}
	{
		System.out.println("Leaf的普通初始化块");
	}	
	public Leaf(){
		//通过super调用父类中有一个字符串参数的构造器
		super("尚硅谷");
		System.out.println("Leaf的构造器");
	}
}
public class LeafTest{
	public static void main(String[] args){
		new Leaf(); 
		//new Leaf();
	}
}
//构造器leaf先行,
//调用super,
//去到Leaf父类Mid,调用Mid构造器
//调用this构造器,构造器默认有个super()构造器,
//去到Root,调用Root构造器
//同理也有super构造器,最后去到Object类
//开始加载类,同时加载静态结构,因此先输出各个类的静态结构
//再输出非静态结构
//最后是输出构造器

//如果执行下一条new Leaf()语句,则少执行各个类的静态结构,因为只执行一次

属性的赋值顺序

①默认初始化
②显式初始化/⑤在代码块中赋值
③构造器中初始化
④有了对象以后,可以通过"对象.属性"或"对象.方法"的方式,进行赋值

  • 执行的先后顺序:① - ② / ⑤ - ③ - ④

类的成员之五:内部类

定义

Java允许将 一个类A 声明在 另一个类B 中,则类A就是内部类,类B 就是外部类

内部类的分类

  1. 可以调用外部类的结构
  2. 可以被static修饰
  3. 可以用四种权限修饰符修饰
  4. 可以用final修饰,表示此类不能被继承,若不用final,就可以继承
  5. 可以用abstract修饰

成员内部类

class B{
    int age;
    public static void sleep(){};//静态方法
    public void eat(){//非静态方法
        sout("吃");
    }
    static class A{//用static修饰成员内部类,同样适用static的规则
        public void show(){
            sout("展示");
            eat();//调用外部类的非静态方法,报错
            sout(age);//调用外部类的属性,报错
            sleep();//调用外部类的静态方法,与 B.this.sleep(); 语句相同
            
        }
    }
    protected class C{
        
    }
    private class D{
        
    }
}
静态成员内部类
非静态成员内部类
class B{
    static class A{
        
    }
    class c{
        
    }
}

局部内部类

方法内
代码块内
构造器内
public void method(){//方法
		//局部内部类
		class AA{
		
		}
	}
	
	{//代码块
		//局部内部类
		class BB{
			
		}
	}
	
	public Person(){//构造器
		//局部内部类
		class CC{
			
		}
	}

内部类应该关注以下三个问题

  1. 如何实例化成员内部类的对象
  2. 如何在成员内部类中区分调用外部类的结构
  3. 开发中局部内部类的使用
public class A{
    psvm{
        B.C cc = new B.C();//创建 静态的成员内部类
        cc.c1();
        
        B b = new B();//创建 非静态的成员内部类
        B.D dd = b.new D();
        dd.d1();
    }
}
class B{
    static class C{
        public void c1(){
            sout("C1");
        }
    }
    class D{
        public void d1(){
            sout("d1");
        }
        
    }
}
//开发中局部内部类的使用
public class InnerClassTest1 {		
	//开发中很少见
	public void method(){
		//局部内部类
		class AA{
			
		}
	}
	//返回一个实现了Comparable接口的类的对象
	public Comparable getComparable(){
	
		//创建一个实现了Comparable接口的类:局部内部类
		//方式一:
//		class MyComparable implements Comparable{
//			@Override
//			public int compareTo(Object o) {
//				return 0;
//			}
//		}
//		return new MyComparable();
		
		//方式二:
		return new Comparable(){
			@Override
			public int compareTo(Object o) {
				return 0;
			}
		};
	}
}

注意点:

  1. 成员内部类和局部内部类,在编译以后,都会生成字节码文件。
    格式:成员内部类:外部类 内 部 类 名 . c l a s s 局 部 内 部 类 : 外 部 类 内部类名.class 局部内部类:外部类 .class数字 内部类名.class

  2. 在局部内部类的方法中(比如:show如果调用外部类所声明的方法(比如:method)中的局部变量(比如:num)的话,要求此局部变量声明为final的。
    jdk 7及之前版本:要求此局部变量显式的声明为final的
    jdk 8及之后的版本:可以省略final的声明

public class InnerClassTest{
    public void method(){
        int num = 10;
        class AA{//局部内部类
            public void show(){
                // num = 20;会报错,因为此时的num已经是用final修饰过了
                sout(num);
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值