6.4 final关键字
- 修饰类、变量和方法,
- 有点类似C#里的 sealed关键字,
- 表示它修饰的类、方法和变量不可改变。
- final可修饰成员变量(包括类变量和实例变量),修饰局部变量、形参。
- 有的书上介绍说final修饰的变量不能被赋值,错误!
- final修饰的变量不可被改变,一旦获得初始值,
- 该变量就不能被重新赋值。
- final变量获得初始值之后不能被重新赋值,
- 因此final修饰成员变量和修饰局部变量时有一定的不同。
6.4.1 final成员变量
- 类初始化时,系统为该类的类变量分配内存并分配默认值:
- 创建对象时,系统为该对象的实例变量分配内存,并分配默认值
- 执行静态初始化块时可以对类变量赋初始值:
- 当执行普通初始化块、构造器时可对实例变量赋初始值。
- 成员变量的初始值可在定义该变量时指定默认值,
- 也可以在初始化块、构造器中指定初始值
好多没写
6.7内部类
- 把一个类放在另一个类的内部定义,
- 内部类(也叫嵌套类),
- 外部类(宿主类)。
- JDK1.1引入内部类,
- 内部类有如下作用。
- 把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。
- Cowley类只有在Cow类里才有效,
- 离开Cow类没意义
- 把Cowley定义成Cow的内部类,不允许其他类访问Cowley
- 内部类成员可直接访问外部类的私有数据
- 内部类被当成外部类成员
- 同一个类的成员之间可互访
- 内部类被当成外部类成员
- 外部类不能访问内部类实现细节
- 如内部类的成员变量
- 匿名内部类用于创建那些仅需要一次使用的类。
- 对于前面介绍的命令模式,当需要传入个Command对象时,重新专门定义 Print Command和 Addcommand两个实现类可能没有意义,
- 因为这两个实现类可能仅需要使用一次。
- 这种情况下,使用匿名内部类将更方便。
- 定义内部类与定义外部类的语法相同,内
- 部类除了需要定义在其他类里面之外,还存在如下区别。
- 内部类比外部类可多用三个修饰符:
- private、 protected、 static
- 外部类不可以使用这三个修饰符
- 非静态内部类不能有静态成员
6.7.1非静态內部类
- 只要把一个类放在另一个类内部定义即可。
- “类内部”包括类中的任何位置,
- 方法中也可定义内部类(称局部内部类)。
- 大部分内部类都被作为成员内部类定义,
- 而不局部内部类。
- 成员内部类与
- 成员变量、方法、构造器和初始化块相似的类成员;
- 局部内部类和匿名内部类不是类成员
- 成员内部类分:
- 静态内部类和非静态内部类,
- static修饰的成员内部类是静态内部类,
- 没有用 static修饰的成员内部类是非静态内部类。
- 同一个Java源文件里定义多个类,那不是内部类
- 是两个互相独立的类。
- 内部类作为其外部类的成员,
- 可用任意访问控制符如 private、 protected和 public
- Cow类里定义Cowleg非静态内部类,
- Cowley类的实例方法中访问Cow的private访问权限的实例变量。
- 粗体字是一个普通类定义,
- 这个类定义放在了另一个类的内部,它就成一个内部类,
- 可用private来修饰这个类
- Cow里含test方法
- 创建了CowLeg对象,并调该对象的info方法
- 在外部类里用非静态内部类时,与平时使用普通类并没区别。
- 编译
- Cow.class,Cow$cowLeg.class,后者是内部类 Cowleg的 class文件,
- 成员内部类(包括静态内部类、非静态内部类)的class文件总是这种形式: Outer Class Sinnerclass class
- 非静态内部类里可直接访问外部类的private成员,
- 1号粗体代码行
- Cowleg类的方法内直接访问其外部类的private实例变量。
- 非静态内部类对象里,保存一个它所寄生的外部类对象的引用
- (当调非静态内部类的实例方法时,须有一个非静态内部类实例,
- 非静态内部类实例必须寄生在外部类实例)
- 图6.6显示程序运行时的内存示意图。
- 非静态内部类的方法访问某变量时,
- 优先在该方法内查找是否存在该名字的局部变量,
- 存在就使用该变量;
- 优先在该方法内查找是否存在该名字的局部变量,
- 不存在,则到该方法所在的内部类中査找是否存在该名字的成员变量
- 如果存在则使用该成员变量;
- 不存在,则到该内部类所在的外部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;
- 依然不存在,编译错误:提示找不到该变量。
- 如果外部类成员变量、内部类成员变量与内部类里方法的局部变量同名,
- 可用this
- 外部类类名.this来区分
- 非静态内部类的成员只在非静态内部类范围内是可知的,
- 不能被外部类直接使用
- 如果外部类要访问非静态内部类成员
- 则须显式创建非静态内部类对象来调用访问其实例成员
- 粗体字试图在外部类方法里访问非静态内部类的实例变量,这将引起编译错误。
- 外部类不允许访问非静态内部类的实例成员还有一个原因,
- main的1号代码创建了一个外部类对象,并调用外部类对象的 accesslnnerpropo
- 此时非静态内部类对象不存在,如果允许accessinnerprop()访问非静态内部类对象,肯定引起错
- 外部类的静态方法、静态代码块不能访问非静态内部类,
- 不能用非静态内部类定义变量、创建实例
- 不许非静态内部类里定义静态成员。
- 非静态内部类不能有静态方法、静态成员变量、静态初始化块,
- 上面三个静态声明都错
6.7.2 静态内部类
- 用static修饰一个内部类,则这个内部类就属于外部类本身,不属于外部类的某个对象
- 因此static修饰的内部类称类内部类,
- 也称为静态内部类。
- 静态内部类可含静态成员,非静态成员。
- 静态内部类不能访问外部类的实例成员,
- 只能访问外部类的类成员。
- 静态内部类的实例方法也不能访问外部类的实例成员,
- 只能访问外部类的静态成员。
- 粗体字代码行定义了一个静态成员变量,
- 这个静态成员变量处于静态内部类中。
- Staticlnnerclass类里定义了一个 accessouterprop方法,
- 这是个实例方法,
- 但不能访问外部类的prop1,因为这是实例变量;
- 但可访问prop2,因为它是静态成员变量。
here!!!