为什么要使用内部类?
主要因为以下三点:
一个类的定义放在另一个类的内部,这个类就叫做内部类。 (类名不需要和文件夹相同)
public class Inner { //像这样的,Contents就叫做内部类 public class Contents { public void f() { System.out.println("hello"); } } }
内部类可以是静态static的,也可用public,default,protected和private修饰。而外部类(类名和文件名相同的类)只能使用public和default来修饰。
内部类分为以下四种:
静态内部类static inner class (also called nested class)
成员内部类member inner class
局部内部类local inner class
匿名内部类anonymous inner class
静态内部类Static Inner Class
1、最简单的内部类形式。
2、类定义时加上static关键字。
3、不能和外部类有相同的名字。
4、只可以访问外部类的静态成员和静态方法,包括了私有的静态成员和方法。
5、生成静态内部类对象的方式为:
OuterClass.InnerClass inner = new OuterClass.InnerClass();
package cy.内部类.静态内部类; public class StaticOuter { private static String name = "Outer"; private int age = 10; public static class StaticInner { @SuppressWarnings("unused") private static String name = "Inner"; public void sayOuterName() { System.out.println("inner:" + StaticOuter.name); } /* * 错误,静态内部类不能访问外部类的非静态成员。 public void sayOuterAge() { System.out.println(age); } */ } public void sayName() { System.out.println(name); } public void sayAge() { System.out.println(age); } }
package cy.内部类.静态内部类; public class TestMain { public static void main(String[] args) { StaticOuter staticOuter = new StaticOuter(); staticOuter.sayAge(); staticOuter.sayName(); StaticOuter.StaticInner staticInner = new StaticOuter.StaticInner(); staticInner.sayOuterName(); } }
运行结果:
10
Outer
inner:Outer
由此可以看出,静态内部类的对象处了没有对外围类对象的应用特权外,与其他所有内部类完全一样。
成员内部类member inner class
package cy.内部类.成员内部类; public class Outer { private static String name = "Outer"; private int age = 10; public class Inner { private final static String name = "Inner"; private int age = 11; public void sayOuterName() { // 内部类中引用外部类对象的静态成员 System.out.println("inner:" + Outer.name); } public void sayInnerName() { System.out.println("inner:" + Inner.name); } public void sayInnerAge() { System.out.println("inner:" + this.age); } public void sayOuterAge() { // 内部类中引用外部类对象的非静态成员 System.out.println(Outer.this.age); } public Outer createOuter() { // 内部类中创建外部类。 return new Outer(); } } public void sayName() { System.out.println(name); } public void sayAge() { System.out.println(age); } public Inner createInner() { // 外部类中创建内部类对象。 return this.new Inner(); } }
public class TestMain { public static void main(String[] args) { Outer outer = new Outer(); outer.sayAge(); outer.sayName(); // 区别于静态内部类的创建方法 Inner inner = outer.new Inner(); inner.sayOuterName(); } }
运行结果:
10
Outer
inner:Outer
局部内部类local inner class
局部类不能用public,protected或者private访问说明符进行声明。它的作用域是被限定在这个局部类的块中。
局部类有一个优势,即对外世界可以完全隐藏起来,其他类中的代码不能访问它。
package cy.内部类.局部内部类; public class Outer { private static String name = "Outer"; private int age = 10; public void doSomeThing() { // 局部内部类,局部内部类,不允许带有 public,protected,private // public class Inner { // protected class Inner { // private class Inner { class Inner { // private static String name; // private final static String name; public void sayInnerName() { System.out.println(name); } public void sayOuterName() { System.out.println(Outer.name); } } Inner inner = new Inner(); inner.sayInnerName(); inner.sayOuterName(); } public void doSomeThingA() { if (this.age > 0) { // 这个Inner与上一个Inner没有任何关系 class Inner { public void sayInnerName() { System.out.println(name); } public void sayOuterName() { System.out.println(Outer.name); } } Inner inner = new Inner(); inner.sayInnerName(); inner.sayOuterName(); } } public void sayName() { System.out.println(name); } public void sayAge() { System.out.println(age); } }
匿名内部类anonymous inner class
假设这创建某个类的一个对象,就不必命名了,这种类成为“匿名内部类”。
package cy.内部类.匿名内部类; public class Outer { public static void main(String[] args) { // 内部类引用外部类对象,使用final。 final String name = "name"; // 接口直接创建对象。类名称并没有直接定义。Java编译器会自动给一个类名称。 // 注意匿名内部类的重要使用场景。“线程” Say s = new Say() { @Override public void say() { System.out.println("hello world " + name); } }; s.say(); } } interface Say { void say(); }
这种语法有点难理解,它的含义是:创建一个实现Say接口的类的新对象,需要实现的方法say定义在{}中。
由于构造器的名字必须跟类名相同,而匿名类没有名称,所以匿名类不能有构造器。取而代之的是,构造器参数传递给超类(superclass)构造器。尤其是在内部类实现接口的时候,不能有任何构造参数。