内部类 (inner class)
定义:在一个类中定义另外一个类,这个类就叫做内部类。
优点:内部类可以让我们将逻辑上相关的一组类组织起来,并由外部类来控制内部类的可见性。
当我们建立一个内部类时,其对象 就拥有了与外部类对象 之间的一种关系,这是通过一个特殊的this reference形成的,使得内部类对象可以随意的访问外部类中所有的成员。
为什么要使用内部类?
1). 在内部类中,可以随意的访问外部类的成员,这可以让我们更好地组织管理我们的代码,增强代码的可读性。
2).内部类可以用于创建适配器类,适配器类是用于实现接口的类。使用内部类来实现接口,可以更好地定位与接口关联的方法在代码中的位置。
3).将内部类设置为私有的,可以隐藏实现的细节。
4).一个方法要继承另一个类且要实现一个接口,并且父类和接口中有一个相同签名的方法,此时,可以用内部类来解决这种问题
通过以下代码演示,可清楚地了解到如何进行内部类和外部类之间进行访问。
1. 在同一类中,从外部类中调用内部类的属性和方法
Outer.java
public class Outer {//外部类 private int member=123; //外部类成员 private void outerMethod(){//外部类方法 System.out.println("outer_Method:"+member); } private class Inner {//内部类 private int member = 789;//内部类成员 private void innerMethod(){//内部类方法 System.out.println("inner_Method:"+member); } } public void print (){ Inner inner = new Inner(); System.out.println("inner_Member:"+inner.member); inner.innerMethod(); } }
Test.java
public class Test {//测试类 public static void main(String[] args) { Outer outer = new Outer(); outer.print(); } }
结果:
inner_Member:789
inner_Method:789
2. 在同一类中,从内部类中调用外部类的属性和方法
Outer.java
package main.java.sameclass2; public class Outer {//外部类 private int member=123; //外部类成员 private void outerMethod(){//外部类方法 System.out.println("outer_Method:"+member); } private class Inner {//内部类 private int member = 789;//内部类成员 private void innerMethod(){//内部类方法 System.out.println("inner_Method:"+member); } private void accessOuter(){//内部类访问外部类 System.out.println("outer_Member:"+Outer.this.member); Outer.this.outerMethod(); } } public void print (){ Inner inner = new Inner(); inner.accessOuter(); } }
Test.java
package main.java.sameclass2; public class Test {//测试类 public static void main(String[] args) { Outer outer = new Outer(); outer.print(); } }
结果:
outer_Member:123
outer_Method:123
3. 在一个类中,调用另一个类中的内部类对象的属性和方法
Outer.java
package main.java.nosameclass1; public class Outer {//外部类 private int member=123; //外部类成员 private void outerMethod(){//外部类方法 System.out.println("outer_Method:"+member); } public class Inner {//内部类 private int member = 789;//内部类成员 private void innerMethod(){//内部类方法 System.out.println("inner_Method:"+member); } public void accessOuter(){//内部类访问外部类 System.out.println("outer_Member:"+Outer.this.member); Outer.this.outerMethod(); } } public void print (){ Inner inner = new Inner(); inner.accessOuter(); } }
Test.java
package main.java.nosameclass1; public class Test {//测试类 public static void main(String[] args) { Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); inner.accessOuter(); } }
结果:
outer_Member:123
outer_Method:123
4. 将一个内部类定义在一个方法中,定义在一个条件名句块中,定义在一个单独的语句块中均可以,但其对外使用的范围也受到相应的限制,不管内部类嵌套的层次有多深,均可以访问外部类的属性及方法。
5. 在方法中定义的内部类,如果要访问方法中定义的本地变量或方法的参数,则变量必须被声明为final.
6. 内部类可以声明为private 或protected;还可以声明为abstract或final.
7. 内部类可以声明为static的,但此时就不能再使用外部类的非static的属性和非静态的方法。
8. 非static的内部类中的属性不能声明为static的,只有最外层或static的内部类中才可以声明static成员。
9. 内部类的派生类
Car.java[外部类和内部类]
package main.java.deriveInnerClass; public class Car {//汽车类(外部类) class Driver{//司机类(内部类) } }
CarDriver.java[ 内部类的派生类]
package main.java.deriveInnerClass; import main.java.deriveInnerClass.Car.Driver; public class CarDriver extends Driver {//派生自内部类(Driver) CarDriver(Car car){ car.super(); //建立内部类与外部类的联系 } }
10. 用内部类实现一个接口
Car.java[接口]
package main.java.anonymous; public interface Car { void run(); void start(); }
Audi.java
package main.java.anonymous; public class Audi { class Q7 implements Car { public void run() { System.out.println("Q7:run"); } public void start() { System.out.println("Q7:start"); } } Car getCar(){ return new Q7(); } }
Test.java
package main.java.anonymous; public class Test { public static void main(String[] args) { Audi audi = new Audi(); audi.getCar().start(); audi.getCar().run(); } }
结果:
Q7:start
Q7:run
11. 匿名的内部类:
Car.java[接口]
package main.java.anonymous; public interface Car { void run(); void start(); }
Audi.java
package main.java.anonymous; public class Audi { class Q7 implements Car{ public void run() { System.out.println("Q7:run"); } public void start() { System.out.println("Q7:start"); } } Car getCar(){ // return new Q7(); return new Car(){//匿名的内部类 public void run() { System.out.println("Q8:run"); } public void start() { System.out.println("Q8:start"); } }; } }
Test.java
package main.java.anonymous; public class Test { public static void main(String[] args) { Audi audi = new Audi(); audi.getCar().start(); audi.getCar().run(); } }
结果:
Q8:start
Q8:run