内部类

在java语言中,可以吧一个类定义到另外一个类的内部,在类里面的这个类就叫内部类,外面的类就叫外部类。在这情况下,这个内部类可以看做外部类的一个成员。还有一种类被称为顶层类,指的是类定义代码不嵌套在其他类定义中的类。
需要注意的是嵌套类与内部类类似,只是嵌套类是C++的说法。 内部类可以分为多种、;主要一下4中:静态内部类,成员内部类,局部内部类,匿名内部类
代码:

class outerClass{
static class innerClass{} //静态内部类
}
class outerClass{
class innerClass{} //成员内部类
}
class outerClass{
public void menberFunction{
static class innerClass{} /局部内部类
}
}
public class MyFrame extends Frame{//外部类
public MyFrame(){
addWindowsLister(new WindowsAdapter()){ //匿名内部类
public void windowsClosing(WindowEvent e){
dispose(); System.exit(0);
}
});
}
}

4.总结代码
静态内部类是指被声明为static的内部类,他可以不依赖内部类而实例,而通常的内部类需要实例化外部类,从而实例化。静态内部类不可以有与外部类有相同的类名。不能访问外部类的普通成员变量,但是可以访问静态成员变量和静态方法(包括私有类型)
一个 静态内部类去掉static 就是成员内部类,他可以自由的引用外部类的属性和方法,无论是静态还是非静态。但是不可以有静态属性和方法、
局部内部类 就是定义在一个代码块的内类,他的作用范围是所在代码块,是内部类中最少使用的一类型。局部内部类跟局部变量一样,不能被public ,protected,private以及static修饰,只能访问方法中定义final类型的局部变量。
匿名内部类是一种没有类名的内部类,不使用class,extends,implements,没有构造函数,他必须继承其他类或实现其他接口。匿名内部类的好处是使代码更加简洁,紧凑,但是带来的问题是易读性下降。他一般应用于GUI编程来实现时间处理等 。
在使用匿名内部类时,需要牢记以下几个原则。
1、内部类没有构造方法
2、匿名内部类不能定义静态成员,方法和类
3、匿名内部类不能是public protected private static
4、只能创建匿名内部类的一个实例
5、一个匿名内部类可以在new后面,这个匿名类必须继承一个父类或实现接口
6、因为匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效

内部类的作用

1、内部类可以很好的实现隐藏

非内部类,是不允许有 private 与protected权限的,但内部类可以

2、内部类拥有外围类的所有元素的访问权限

3、可是实现多重继承 !!

4、可以避免修改接口而实现同一个类中两种同名方法的调用。

举例说明如下:
1.实现隐藏

平时我们对类的访问权限,都是通过类前面的访问修饰符来限制的,一般的非内部类,是不允许有 private 与protected权限的,但内部类可以,所以我们能通过内部类来把我们的信息对同一包中的其他类隐藏起来。可以看下面的例子:

接口

public interface InnerInterface {

void innerMethod();

}

具体类

/**
 * 实现信息隐藏
 */
public class OuterClass {

    /**
     * private修饰内部类,实现信息隐藏
     */
    private class InnerClass implements InnerInterface {

        @Override
        public void innerMethod() {
            System.out.println("实现内部类隐藏");
        }

    }

    public InnerInterface getInner() {

        return new InnerClass();

    }

}

调用程序

public class Test {

    public static void main(String[] args) {

        OuterClass outerClass = new OuterClass();

        InnerInterface inner = outerClass.getInner();

        inner.innerMethod();
        
    }
}

打印

实现内部类隐藏

从这段代码里面我只知道OuterClass的getInner()方法能返回一个InnerInterface接口实例但我并不知道这个实例是这么实现的。而且由于InnerClass是private的,所以我们如果不看代码的话根本看不到这个具体类的名字,所以说它可以很好的实现隐藏。

2.可以无条件地访问外围类的所有元素

为什么可以引用:
内部类虽然和外部类写在同一个文件中, 但是编译完成后, 还是生成各自的class文件,内部类通过this访问外部类的成员。
1 编译器自动为内部类添加一个成员变量, 这个成员变量的类型和外部类的类型相同, 这个成员变量就是指向外部类对象(this)的引用;
2 编译器自动为内部类的构造方法添加一个参数, 参数的类型是外部类的类型, 在构造方法内部使用这个参数为内部类中添加的成员变量赋值;
3在调用内部类的构造函数初始化内部类对象时,会默认传入外部类的引用。

编译指令 javac classpath(.java文件的路径)
反编译指令 javap -v(详细信息) classpath(.class文件的路径)

/**
 * 内部类无条件访问外部类元素
 */
public class DataOuterClass {

    private String data = "外部类数据";

    private class InnerClass {

        public InnerClass() {

            System.out.println(data);

        }

    }

    public void getInner() {

        new InnerClass();

    }

    public static void main(String[] args) {

        DataOuterClass outerClass = new DataOuterClass();

        outerClass.getInner();

    }

}

打印

外部类数据

data这是在DataOuterClass定义的私有变量。这个变量在内部类中可以无条件地访问.

3.可以实现多重继承

我们知道 java 是不允许使用 extends 去继承多个类的。内部类的引入可以很好的解决这个事情。
以下引用 《Thinking In Java》中的一段话:

每个内部类都可以队里的继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类没有影响
如果没有内部类提供的、可以继承多个具体的或抽象的类的能力,一些设计与编程问题就难以解决。
接口解决了部分问题,一个类可以实现多个接口,内部类允许继承多个非接口类型(类或抽象类)。

我的理解 Java只能继承一个类这个学过基本语法的人都知道,而在有内部类之前它的多重继承方式是用接口来实现的。但使用接口有时候有很多不方便的地方。比如我们实现一个接口就必须实现它里面的所有方法。而有了内部类就不一样了。它可以使我们的类继承多个具体类或抽象类。如下面这个例子:

类一

public class ExampleOne {

    public String name() {

        return "inner";

    }

}

类二

public class ExampleTwo {

    public int age() {

        return 25;

    }

}

类三


public class MainExample {

   /**
    * 内部类1继承ExampleOne
    */
   private class InnerOne extends ExampleOne {

       public String name() {

           return super.name();

       }

   }

   /**
    * 内部类2继承ExampleTwo
    */
   private class InnerTwo extends ExampleTwo {

       public int age() {

           return super.age();

       }

   }

   public String name() {

       return new InnerOne().name();

   }

   public int age() {

       return new InnerTwo().age();

   }

   public static void main(String[] args) {

       MainExample mi = new MainExample();

       System.out.println("姓名:" + mi.name());

       System.out.println("年龄:" + mi.age());

   }

}

大家注意看类三,里面分别实现了两个内部类 InnerOne,和InnerTwo ,InnerOne类又继承了ExampleOne,InnerTwo继承了ExampleTwo,这样我们的类三MainExample就拥有了ExampleOne和ExampleTwo的方法和属性,也就间接地实现了多继承。
4.避免修改接口而实现同一个类中两种同名方法的调用。

大家假想一下如果,你的类要继承一个类,还要实现一个接口,可是你发觉你继承的类和接口里面有两个同名的方法怎么办?你怎么区分它们??这就需要我们的内部类了。看下面的代码

接口

public interface Incrementable{

 void increment();

}
类 Increment

public class Increment {

   public void increase() {

       System.out.println("Increment increase()");

   }

   static void f(Increment f) {

       f.increase();

   }

}

此时接口和类中有相同的方法increase()。当不用内部类直接实现这两个类时

public class IncreaseNoInner extends Increment implements Incrementable {

    public void increase() {

        //代码

    }

}

此时increase()方法存在歧义,是属于覆盖Increment这里的方法呢?还是Incrementable这里的方法。我怎么能调到Increment这里的方法?显然这是不好区分的。而我们如果用内部类就很好解决这一问题了。看下面代码

public class IncreaseWithInner extends Increment{

    private int i = 0;

    private void incr() {

        i++;

        System.out.println(i);

    }

    private class Closure implements Incrementable {
        @Override
        public void increase() {

            incr();

        }
    }

    Incrementable getCallbackReference() {

        return new Closure();

    }


    public static void main(String[] args) {

        IncreaseWithInner increase=new IncreaseWithInner();
        increase.increase();
        increase.getCallbackReference().increase();

    }


}

我们可以用内部类来实现接口,这样就不会与外围类的方法冲突了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值