Java 内部类

原地址

1.成员内部类

什么是成员内部类?
在外部类内部直接定义(不在方法内部或代码块内部)的类就是成员式内部类。
特点:1)可以直接访问外部类的所有成员,包括private
     2)可以用static、private、public等等修饰,而外部类只能用public或缺省修饰
     3)普通成员内部类只能够由对象调用
     4)静态内部类不会在外部类加载时加载,可以由类来调用
public class Outer{
    private int size;
    public class Inner {
        public void dostuff() {
            size++;
        }
    }
    public void testTheInner() {
        Inner in = new Inner();
        in.dostuff();
    }
}
若有 static 修饰符,就为类级,否则为对象级。**类级可以通过外部类直接访问,对象级需要先生成外部的对象后才能访问**。可以理解为普通成员内部类在外部只能通过Outer.Inner = outer.getInnerInstance();的形式进行初始化。
public class Singleton {  
    private static class SingletonHolder {  
        private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
        return SingletonHolder.INSTANCE; 
    }  
}
静态内部类可以包含static成员。在上例中当调用getInstance(),private static final Singleton INSTANCE = new Singleton();才会被执行。可见静态内部类并不会在其外部类加载时加载,当且仅当其某个静态成员(静态域、构造器、静态方法等)被调用时发生,并且只加载一次。

2.局部内部类

顾名思义,把类放在方法内。

    class Outer {
        public void doSomething(){
            class Inner{
                public void seeOuter(){
                }
            }
        }
    }

A、方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
B、方法内部类对象不能使用该内部类所在方法的非final局部变量。
因为方法的局部变量位于栈上,只存在于该方法的生命期内。当一个方法结束,其栈结构被删除,局部变量成为历史。但是该方法结束之后,在方法内创建的内部类对象可能仍然存在于堆中!例如,如果对它的引用被传递到其他某些代码,并存储在一个成员变量内。正因为不能保证局部变量的存活期和方法内部类对象的一样长,所以内部类对象不能使用它们。
下面是完整的例子:
class Outer {
public void doSomething(){
final int a =10;

        class Inner{

            public void seeOuter(){
                System.out.println(a);
            }
        }
        Inner in = new Inner();
        in.seeOuter();
    }
    public static void main(String[] args) {
        Outer out = new Outer();
        out.doSomething();
    }
 }

C、方法内部类的修饰符。
与成员内部类不同,方法内部类更像一个局部变量。 可以用于修饰方法内部类的只有final和abstract。
D、静态方法内的方法内部类。
静态方法是没有this引用的,因此在静态方法内的内部类遭受同样的待遇,即:只能访问外部类的静态成员

3.匿名内部类(可以参考匿名类)

顾名思义,没有名字的内部类。表面上看起来它们似乎有名字,实际那不是它们的名字。
A、继承式的匿名内部类。
class Car {
public void drive(){
System.out.println(“Driving a car!”);
}
}

class Test{
    public static void main(String[] args) {
        Car car = new Car(){
            public void drive(){
                System.out.println("Driving another car!");
            }
        };
        car.drive();
    }
}

结果输出了:Driving another car! Car引用变量不是引用Car对象,而是Car匿名子类的对象。
建立匿名内部类的关键点是重写父类的一个或多个方法。再强调一下,是重写父类的方法,而不是创建新的方法。因为用父类的引用不可能调用父类本身没有的方法!创建新的方法是多余的。简言之,参考多态。

B、接口式的匿名内部类。
interface Vehicle {
public void drive();
}

class Test{
    public static void main(String[] args) {
        Vehicle v = new Vehicle(){
            public void drive(){
                System.out.println("Driving a car!");
            }
        };
        v.drive();
    }
}

上面的代码很怪,好像是在实例化一个接口。事实并非如此,接口式的匿名内部类是实现了一个接口的匿名类。而且只能实现一个接口。
C、参数式的匿名内部类。
class Bar{
void doStuff(Foo f){}
}

interface Foo{
    void foo();
}

class Test{
    static void go(){
        Bar b = new Bar();
        b.doStuff(new Foo(){
            public void foo(){
                System.out.println("foofy");
            }
        });
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值