普通内部类
如果一个类只需要在另一个类内部使用,可以考虑将它写成内部类。
内部类拥有其外部类所有成员的访问权,因为内部类中隐含了一个外部类的引用,可通过 OuterClass.this 获得。
普通内部类中不可定义static的字段,除非它是final的。
利用内部类可以实现类似“多继承”,因为内部类继承哪个父类或实现哪些接口都与外部类无关。
若内部类为private,外界将完全不可见,只有外部类可见。
若内部类为public,可通过外部类对象.new关键字获得。
----------
interface ForInner1 { void printSomething(); } class OutClass { private int id; private String name; public OutClass() { } public OutClass(int id, String name) { this.id = id; this.name = name; } private class Inner1 implements ForInner1 { private String info; // 自己的成员 @Override public void printSomething() { info = "hello"; System.out.println(id + "-" + name + "-" + info); // 通过Outer.this返回其外部类引用 System.out.println(OutClass.this); } } public class Inner2 { public void printMe() { System.out.println(this); } } public Inner1 getInner1() { return new Inner1(); } } public class NormalNestedClassTest { public static void main(String[] args) { OutClass outClass = new OutClass(10, "boy"); // 错误 Inner1不可见 // OutClass.Inner1 in1 = outClass.getInner1(); // 错误 Inner1不可见 // outClass.getInner1().printSomething(); // 可通过接口访问 ForInner1 inner1 = outClass.getInner1(); inner1.printSomething(); OutClass.Inner2 inner2 = outClass.new Inner2(); inner2.printMe(); } }
----------
输出:
10-boy-hello
demos.innerClass.OutClass@7852e922
demos.innerClass.OutClass$Inner2@4e25154f
静态内部类
如果不需要内部类与外部类的对象有关联,可以使用静态内部类
静态内部类与普通内部类非常不同,若为public的,则与普通的静态类无异。
静态内部类不能访问外部类的非静态成员,不隐含外部类对象的引用。
----------静态内部类-----
class OuterClass { private static String name="OuterClass"; //在外部类中使用静态内部类 private Nest1 nest1 = new Nest1(); public void printNest1(){ nest1.print(); } private static class Nest1 { public void print() { // 只能访问外部类的静态成员 System.out.println(this +" name:"+ name); } } public static class Nest2 { Nest2(){ System.out.println(this); } } } public class StaticNestedClassTest { public static void main(String[] args) { OuterClass out1 = new OuterClass(); OuterClass out2 = new OuterClass(); out1.printNest1(); out2.printNest1(); // public静态内部类 无需外部类即可创建 OuterClass.Nest2 nest2 = new OuterClass.Nest2(); } }
--------------------------
匿名内部类
这种方式将类的声明和实现放在了一起,并且省略了类名。
但是需要一个接口或父类来描述。
-----------匿名内部类----
//内部类 接口 interface Iinner { void printSomething(); } // 匿名内部类 父类 class Finner { String name; Finner() { } Finner(String name) { this.name = name; } public void printSomething() { System.out.println(this + " name:" + name); } } class Outer { // 匿名内部类1 实现接口,然后返回 public Iinner getInner1() { return new Iinner() { @Override public void printSomething() { System.out.println("同一接口的第一种实现"); } }; } //或者 实现接口而后调用 //等同于父类不实现,交由匿名内部类实现,这样可限制父类的类型 //另一个意义 可实现同一个接口的不同实现 public void printThing(){ new Iinner(){ @Override public void printSomething() { System.out.println("同一接口的第二种实现"); } }.printSomething(); } // 匿名内部类2 继承一个父类 // 可通过父类构造函数传递参数到匿名内部类内部 public Finner getInner2(String name) { Finner a= new Finner(name) { //隐秘的复写了父类的方法 @Override public void printSomething() { System.out.println("I am "+name); } public void say(){ //无法被调用 } }; return a; } // 匿名内部类3 直接传参到匿名内部类内部 参数为final public Finner getInner3(String str) { return new Finner() { private String s = str; public void printSomething() { System.out.println(s); } }; } } public class InnerTest { public static void main(String[] args) { Outer out = new Outer(); out.getInner1().printSomething(); out.printThing(); out.getInner2("tom").printSomething(); out.getInner3("hehe").printSomething(); } }
--------------------------
输出:
同一接口的第一种实现
同一接口的第二种实现
I am tom
hehe
多继承
-----------
class Pen { protected String name = "pen"; {System.out.println("I have a pen");} } class Apple { protected String name = "apple"; {System.out.println("I have an apple");} } public class ApplePen { private class C1 extends Pen {} private class C2 extends Apple {} public void haha() { C1 c1 = new C1(); C2 c2 = new C2(); System.out.println("en " + c2.name +"-"+ c1.name); } public static void main(String[] args) { ApplePen ap = new ApplePen(); ap.haha(); } }
-----------
内部类产生 Outer$Inner.class
匿名内部类产生 Outer$1.class
end