内部类
把一个类放在另一个类中定义,这个定义在其他内部的类被称为内部类,包含内部类 的类被成为外部类,Java从JDK1.1开始引入了内部类的定义。
内部类的作用:
- 内部类提供了更好的封装,可以把内部类隐藏在外部类中,不允许同一个包中的其他类访问该类。假如需要创建一个Cow类,Cow类需要一个CowLeg对象,CowLeg对象只有在Cow类中才有作用,离开了Cow类后没有任何作用,就可以在Cow类中定义一个CowLeg类。CowLeg类只有在Cow类中才有作用,离开了Cow之后就没有任何意义。
- 内部类成员可以直接访问外部类的私有数据,因为内部类是被当做外部类的成员,同一个类中的成员可以相互访问,但是外部类是不可访问内部类的细节的,例如内部类的成员变量
- 匿名内部类适用于那些仅需要一次的类
- 内部类比外部类多了三个修饰符:private,protected,static。
- 非静态内部类是不可以创建静态成员的。
内部类的种类:匿名内部类,方法内部类,成员内部类。
- 成员内部类的使用方法
/* * 成员内部类的定义 */ //定义一个接口 interface Animal { void shout(); } public class Example { public static void main(String[] args) { // 定义一个成員内部类实现Animal接口 class Cat implements Animal { @Override public void shout() { System.out.println("喵喵"); } } // 调用Shout方法并传入Cat对象 Shout(new Cat()); } // 定义一个静态方法animalShout() public static void Shout(Animal an) { an.shout(); } }
- 匿名内部类的使用
语法格式:
new 父类(参数列表)或 父接口(){
匿名内部类的实现部分
}
//定义动物类接口 interface Animal { public void shout(); } public class Example01 { public static void main(String[] args) { // 定义匿名内部类作为参数传递给animalShout()方法 animalShout(new Animal() { // 实现方法 public void shout() { System.out.println("喵喵。。"); } }); } // 定义静态方法animalShout() public static void animalShout(Animal an) { an.shout(); } }
大部分时候,内部类一般做为成员内部类来使用,成员内部类是一种与成员,变量,方法,构造器和初始代码块相似的类成员;局部内部类和方法内部类则不是类成员。
成员内部类分为两种:静态内部类和非静态内部类,使用static修饰的内部类时静态内部类,没有使用static修饰符的时非静态内部类。
一个Java源文件中定义了多个类,那种情况不是内部类,他们时相互独立的静态内部类,内部类一定是放在一个类的类体中定义的。
在非静态内部类中的方法访问一个变量时,系统会优先在该方法中查找是否有该变量,如果没有,就到它所在的内部类中查找同名的变量,如果还没有查找到,就到内部类所在的外部类中查找同名的变量,如果依然不存在,系统就会报错。
如果外部类成员变量,内部类成员变量和内部类方法中的成员变量同名,可以使用this,外部类类名.this作为限定区分。
package cn.it.demo01; public class DiscerVariable { private String prop1="外部类的成员变量"; private class InClass{ private String prop="内部类的成员变量"; public void info() { String prop="局部变量"; //通过外部类的类名.this.VarName访问外部类的成员变量 System.out.println("外部类的成员变量值:"+DiscerVariable.this.prop1); //通过内部类的this来访问内部类的成员变量: System.out.println("内部类的成员变量值:"+this.prop); //直接访问局部变量 System.out.println("局部变量值:"+prop); } } public void test() { InClass in=new InClass(); in.info(); } public static void main(String[] args) { new DiscerVariable().test(); } }
非静态内部类是可以访问外部类分私有成员变量,如果外部类是要访问内部类的成员变量是要显示创建非静态内部类的对象来访问其实例成员。
package cn.it.demo01; public class Outer { private int outProp = 9; class Inner { private int inPorp = 5; public void acessOutProp() { // 非静态内部类时可以直接访问外部类的成员变量的 System.out.println("外部类的outProp值:" + outProp); } } public void accessInnerPorp() { // 外部类时不能直接访问内部类的成员变量的 // 以下代码出项错误 // System.out.println("内部类的成员变量:"+inPorp); // 如需访问内部类的成员变量必须显示的创建内部类的对象 System.out.println("内部类的inPorp值:" + new Inner().inPorp); } public static void main(String[] args) { Outer out = new Outer(); out.accessInnerPorp(); } }
根据静态成员不能访问非静态成员以及以上代码可以推出:外部类的静态方法,静态代码块是不能访问非静态内部类的,总之,不能外部类的静态成员中直接使用非静态的内部类。
静态内部类:
使用static修饰的一个内部类就是一个静态内部类,这个静态内部类是属于外部类的本身,而不是属于外部类的某个对象。
静态内部类是不可以访问外部类的非静态成员的。
注意:静态内部类的非静态方法也是不可以访问外部类的非静态成员的,因为,静态内部类是外部类相关的,静态内部类的对象不是寄存在外部类的实例对象中,而是寄存在外部类的本身,当静态内部类对象存在时,并不存在一个被他寄存的外部类实例对象,静态内部类只持有一个外部类的引用,并没有外部类的实例对象的引用,如果允许静态内部类访问外部类的非静态成员,但找不到被寄存的外部类对象,将引起错误。
外部类依然不能直接访问静态内部类的成员变量,但可以使用类名来直接访问内部类的静态成员,也可以创建一个内部类成员来访问静态内部类的非静态成员。
package cn.it.demo01; public class AccessStaticInnerClass { static class StaticInnerClass { private static int prop1 = 5; private int prop2 = 9; } public void accessInnerProp() { // System.out.println("prop1"); // 以上代码出现错误,应该为如下形式 System.out.println(StaticInnerClass.prop1); System.out.println(new StaticInnerClass().prop2); } }