- 内部类说白了就是类中有类
外部类:宿主类
- 内部类主要有以下作用:记住了3个字:多继承。。。
- 内部类分类,主要有下面4种:
- 非静态内部类
内部类的上一级程序单元是外部类,他就有4个作用域:可以使用任意的访问控制符。
/** * * @version 1L * @author LinkinPark * @since 2014-11-5 * @motto 梦似烟花心似水,同学少年不言情 * @desc ^在linkin类中定义一个binger的非静态内部类,并在binger类的实例方法中直接访问linkin的实例属性 * */public class Linkin { private String name = "LinkinPark"; private class Binger { private String andress = "Binger"; public String getAndress() { return andress; } public void setAndress(String andress) { this.andress = andress; } // 非静态内部类的实例方法 public void test() { System.out.println("内部类中的属性" + andress); System.out.println("外部类中的属性" + name); } } //外部类的实例方法 public void test(){ Binger binger = new Binger(); binger.test(); } public static void main(String[] args) { Linkin linkin = new Linkin(); linkin.test(); }}
编译上面的程序,可以看到文件所在路径生成了2个class文件:
成员内部类(包括静态内部类,非静态内部类)的class总是这样子:OutClass$ InnerClass.class。
注意上面的代码:当调用非静态内部类的实例方法时,必须要有一个非静态内部类的实例,而且这个实例必须寄存在外部类实例中。
那么问题来了:若外部类字段,内部类字段,内部类方法变量同名,则具体的访问方式是怎么样的呢?1,访问外部类的字段:外部类类名.this.字段
2,访问内部类字段:this.字段
3,访问内部类方法的局部变量:字段代码如下:
public class Linkin { private String name = "LinkinPark..."; private class Binger { private String name = "Binger..."; // 非静态内部类的实例方法 public void test() { String name = "huhu..."; System.out.println("局部变量的属性" + name); System.out.println("内部类中的属性" + this.name); System.out.println("外部类中的属性" + Linkin.this.name); } } //外部类的实例方法 public void test(){ Binger binger = new Binger(); binger.test(); } public static void main(String[] args) { Linkin linkin = new Linkin(); linkin.test(); }}
- 在外部类以内访问非静态内部类
非静态内部类对象必须寄存在外部类对象中,但是外部类对象不一定非要有非静态内部类对象寄存其中。
因此外部类对象访问非静态内部类成员时,可能非静态内部类对象就压根没存在,反过来:要是非静态内部类对象访问外部类成员时,外部类对象一定存在的。
public class Linkin { private String name = "LinkinPark..."; private class Binger { private String name = "Binger..."; private String huhu = "Binger..."; // 非静态内部类的实例方法 public void test() { String name = "huhu..."; //注意了:java不允许在非静态内部类中定义静态成员:包括静态方法,静态属性,静态初始化块。。。 //static String name = "huhu..."; System.out.println("局部变量的属性" + name); System.out.println("内部类中的属性" + this.name); System.out.println("外部类中的属性" + Linkin.this.name); } } //外部类的实例方法 public void test(){ //注意了:外部类不允许直接访问非静态内部类的实例属性,如果确实需要访问的话,必须显式new内部类对象出来 //System.out.println(huhu); System.out.println(new Binger().huhu); Binger binger = new Binger(); binger.test(); } public static void main(String[] args) { //注意了:外部类的静态成员也不可以直接使用非静态内部类,下行代码编译报错。 //new Binger(); Linkin linkin = new Linkin(); linkin.test(); }}
- 在外部类以外访问非静态内部类
非静态内部类对象是存放在外部类的对象里的,因此在创建非静态内部类对象之前,必须先创建其外部类的对象。OuterInstance.new InnerClass([参数列表])。
class Linkin { String name = "LinkinPark..."; class Binger { String name = "Binger..."; public Binger(){ } public Binger(String name){ this.name = name; } public void test() { System.out.println("帝王注定孤独,江山与他何干..."); } } }//其实在外部类中或者外部类外创建内部类对象(比如一个子类对象),都要使得内部类保持外部类对象的一个引用。//前者可以通过外部类对象直接new内部类出来,后来将外部类作为参数传入内部类的子类构造器中。public class LinkinTest extends Linkin.Binger{ //No enclosing instance of type Linkin is available due to some intermediate constructor invocation //下面的构造器必须在,而且还要必须传入一个外部类,因为非静态内部类对象中必须存在一个外部类对象的引用的 public LinkinTest(Linkin linkin){ linkin.super(); //linkin.super("huhu"); } public static void main(String[] args) { //创建内部类对象 Linkin.Binger binger = new Linkin().new Binger("忽忽"); //访问属性 System.out.println(new Linkin().name);//LinkinPark... System.out.println(new Linkin().new Binger().name);//Binger... System.out.println(new Linkin().new Binger("忽忽").name);//忽忽 } }
- 静态内部类
使用static修饰内部类,该内部类属于其外部类,而不属于外部类的实例;静态内部类可包括静态成员也可包括非静态成员。
根据静态成员不能访问非静态成员的规定,所以静态内部类不能访问外部类实例成员,只能访问外部类的静态成员。即使是静态内部类的方法也不可以。
为毛静态内部类实例方法中也不能访问外部类的实例属性?
静态内部类对象不是寄存在外部类对象中的,而是寄存在外部类的类中。如果允许上面的操作,但是找不到外部类的实例对象,肯定要引起错误的呀。
/** * * @version 1L * @author LinkinPark * @since 2014-11-5 * @motto 梦似烟花心似水,同学少年不言情 * @desc ^static不可以修饰外部类,但是可以修饰内部类 */class Linkin { String name1 = "LinkinPark..."; static String name3; static class Binger { String name2 = "Binger..."; public Binger(){ } public Binger(String name2){ this.name2 = name2; } public void test() { //Cannot make a static reference to the non-static field name1 //静态成员不能访问非静态成员 //System.out.println(name1); System.out.println(name3); } } }
- 在外部类之内访问静态内部类
public class Linkin { private String name = "LinkinPark"; private static int age = 25; static class Binger { private String name1 = "Binger"; private static int age1 = 24; public void show() { // System.out.println(name);不能访问:静态的不能访问非静态的 System.out.println(new Linkin().name);// 可以访问 System.out.println(age);// 可以访问 } } public void test() { // System.out.println(name1);不能访问 // System.out.println(age1);不能访问 System.out.println(new Binger().name1); System.out.println(Binger.age1); new Binger().show(); } public static void main(String[] args) { new Linkin().test();//Binger 24 LinkinPark 25 }}
- 在外部类以外访问静态内部类
创建内部类对象:new OuterClass.InnerClass([参数列表])。注:静态内部类的全名应该是OuterClass.InnerClass,所以要看作是一个整体。
public class Linkin { static String name3; static class Binger { static String name2; public void show(){ System.out.println("静态内部类实例方法..."); } public static void staticShow(){ System.out.println("静态内部类静态方法..."); } } public static void main(String[] args) { Linkin.Binger binger = new Linkin.Binger(); Linkin.Binger.staticShow();//调用静态内部类静态方法 binger.show();//调用静态内部类的实例方法 }}
- 局部内部类
对于局部成员而言,不管是局部变量,还是局部内部类,他们的上一级程序单元是方法,而不是类,所以使用static完全没有意义。不仅如此,因为局部成员的作用域是所在的方法,其他程序单元永远不能访问另一个方法中的局部变量,所以局部变量不可以使用访问控制符修饰。
局部内部类:定义在方法里的内部类。
特点:不能在宿主类以外的地方使用,局部内部类也不能使用访问修饰符和static修饰。
局部内部类只能访问方法中final修饰的局部变量:因为final修饰的变量相当于一个常量,其生命周期超出了方法运行的生命周期。
关于上面这一点,我也不是很懂,记住就好了。其实一般也不会在一个方法中来定义一个内部类,这个有点复杂了,就好比不会在一个接口里面定义一个内部接口,我是没见过。
public class Linkin { public void test(){ class Binger{ } class Binger1{ } }; public static void main(String[] args) { final int age = 0; class Binger{ String name; public void test(){ //注意了:局部内部类中访问局部变量必须使用final修饰那个变量 System.out.println(age); } } class Binger1 extends Binger{ String name1; } Binger1 binger1 = new Binger1(); binger1.name = "LinkinPark..."; binger1.name1 = "binger..."; System.out.println(binger1.name+"---"+binger1.name1); }}
编译上面的程序看到有5个class,这表明局部内部类的class文件总是以下命名方式:OutClass$InnerClass.class,注意到局部内部类的文件名的class文件比内部类的class文件多了一个数字,这是因为同一个类中不可能有2个同名的成员变量,但是同一个类中可能有2个或者2个以上的同名的局部内部类,所以java为局部内部类的class文件增加了一个数字,用于区分。
- 匿名内部类
创建匿名[Anonymity]内部类时会立即创建一个该类的实例,这个类定义立即消失,匿名内部类不能重复使用。匿名内部类访问局部变量时也必须使用final修饰那个变量。
public class Linkin { //定义一个方法,其中的参数要用到下面的抽象类 public static void test(Binger binger){ System.out.println(binger.getName()); System.out.println(binger.test()); } //定义一个方法,其中的参数要用到下面的接口 public static void test1(Ihuhu huhu){ System.out.println(huhu.test()); } public static void main(String[] args) { //直接传入一个匿名内部类,只是在调用这个方法的时候使用一次 Linkin.test(new Binger(){ @Override //这里是必须要实现的抽象方法 public String test() { return "这里把name的get方法返回了。。。"; } @Override //匿名内部类当然可以重写继承过来的方法 public String getName() { return "linkinPark..."; } }); Linkin.test1(new Ihuhu(){ @Override//必须要实现接口里面的所有的方法呀 public String test() { return "huhu..."; } }); }}abstract class Binger{ private String name = "binger..."; public Binger(){ } public Binger(String name){ this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } //定义一个抽象方法 abstract public String test();}interface Ihuhu{ public String test();}