Java 内部类知识点

1、当生成一个内部类的对象时,此对象与制造它的外围对象之间就有了一种联系,所以它能访问其外围对象的所有成员,而不需要任何条件。此外,内部类还拥有其外围类的所有元素的访问权。这是如何做到的呢?当某个外围类的对象创建了一个内部类对象时,此内部类对象必定会秘密地捕获一个指向那个外围类对象的引用。然后,在你访问此外围类的成员时,就是用那个引用来选择外围类的成员。而这些所有细节,都是编译器帮你处理了。

如果不需要内部类对象和其外部类对象之间有关系,那么可以将内部类声明为static,静态内部类不会隐式的持有一个外部类对象的引用。静态内部类与普通内部类还有一个区别,普通内部类的字段与方法,只能放在类的外部层次上,所以普通的内部类不能有static数据和static字段,也不能包含静态内部类,而静态内部类可以包含所有这些东西

2、在拥有外部类对象之前是不可能创建内部类对象的。这是因为内部类对象会暗暗地连接到创建它的外部类对象上。示例:

A a= new A();

B b =a.new B();//其中A是外部类,B是内部类 

但是,如果你创建的是嵌套类(静态内部类),那么它就不需要对外部类对象的引用。

3、匿名内部类

匿名内部类也就是没有名字的内部类

正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写

但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口,形式如:new XXX(){};

public  class Parcel{

public Wrapping wrapping(final int x){

return new Wrapping(){

private int value = x ;

public int value(){

return value++;

}}}}

a)Wrapping既可以是一个接口,也可以是一个已定义了的类 -- 匿名内部类既可以扩展类,也可以实现接口,但是 不能两者兼备。而且如果是实现接口,也只能实现一个接口;

b)在匿名类中定义字段时,还能够对其执行初始化操作;

c)如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译器会要求其参数引用是final的;

4、接口内部的类

正常情况下,不能在接口内部放置任何代码,但静态内部类可以作为接口的一部分。你放到接口中的任何类都会自动的是public和static。因为类是static的,只是将静态内部类置于接口的命名空间内,这并不违反接口的规则。你甚至可以在内部类中实现其外围接口,示例:

public interface ClassInterface{

void howdy();

class Test implements ClassInterface{

public void howdy(){

System.out.println("HowDy");

}

public static void main(String[] args){

new Test().howdy();

}}}

如果你想要创建某些公共代码,使得它们可以被某个接口的所有不同实现所共有,那么使用接口内部的静态类会显得非常方便。

5、内部类有效的解决了“多重继承”问题

内部类允许继承多个非接口类型(类或者是抽象类)。为了看到更多的细节,让我们考虑这样一种情形:即必须在一个类中以某种方式实现两个接口。由于接口的灵活性,你有两种选择:使用单一类,或者使用内部类。

interface A {}

interface B {}

class X implements A,B{}

class Y implements A{

B makeB(){

return new B(){};

}}

如果拥有的是抽象类或具体的类,而不是接口,那就只能使用内部类才能实现多重继承。

class D{}

abstract class E{}

class Z extends D{

E makeE(){ return new E(){};}

}

如果不需要解决“多重继承”的问题,那么自然可以用别的方式编码,而不需要使用内部类。

6、闭包

闭包是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域。通过这个定义,可以看出内部类是面向对象的闭包,因为它不仅包含外部类对象的信息,还自动拥有一个指向此外部类对象的引用,在此作用域内,内部类有权操作所有的成员,包括private成员。

7、内部类的继承

因为内部类的构造器必须连接到指向其外部类的引用,所以在继承内部类的时候,事情会变得有点复杂。问题在于,那个指向外部类对象的“秘密”引用必须被初始化,而在子类中不再存在可连接的默认对象。要解决这个问题,必须使用特殊的语法来明确说明它们之间的关联:

class WithInner{

class Inner{}

}

public class InheriInner extends WithInner.Inner{

//InheriInner(){} won't compile

InheriInner(WithInner wi){

wi.super();

}}

可以看到,InheriInner只继承自内部类,而不是外围类。但是当要生成一个构造器时,默认的构造器并不算好,而且不能只是传递一个指向外部类对象的引用。此外,必须在构造器内使用如下语法:

enclosingClassReference,super();

这样才提供了必要的引用,然后程序才能编译通过。

8、内部类标识符

外部类的名字+$+内部类的名字。如果内部类是匿名的,编译器会简单地产生一个数字作为其标识符。如果内部类是嵌套在别的内部类之中,只需直接将它们的名字加在其外部类标识符与$的后面。

Counter.class

LocalInnerClass$1.class

LocalInnerClass$1LocalCounter.class

LocalInnerClass.class

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值