内部类 (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