关于java 内部类
[b][size=4]“内部类”带有一个“类”字,我们会很自然的将它与一般的外部类相提并论,但实际上从这个角度去理解是不全面的,有时甚至会产生错误。“内部类”重点在“内部”两个字,可以理解为(外部类)的内部的与“类”相似的成员.[/size][/b][b][size=4]一个典型的例子就是它有类成员的封闭等级:private ,protected,默认(friendly),public[/size][/b]
[b][size=4]而一个外部类只有默认(friendly),public[/size][/b]
[b][size=4]因此“内部类”更偏向与成员,从这个角度理解就不容易产生混淆。[/size][/b]
[b][size=4]找了一些有价值的资料,请大家看一下,英文好的直接去看JLS.[/size][/b]
内部类总结:
1.首先,把内部类作为外部类的一个特殊的成员来看待,因此它有类成员的封闭等级:private ,protected,默认(friendly),public
它有类成员的修饰符: static,final,abstract
2.非静态内部类nested inner class,内部类隐含有一个外部类的指针this,因此,它可以访问外部类的一切资源(当然包括private)
外部类访问内部类的成员,先要取得内部类的对象,并且取决于内部类成员的封装等级。
非静态内部类不能包含任何static成员.
3.静态内部类:static inner class,不再包含外部类的this指针,并且在外部类装载时初始化.
静态内部类能包含static或非static成员.
静态内部类只能访问外部类static成员.
外部类访问静态内部类的成员,循一般类法规。对于static成员,用类名.成员即可访问,对于非static成员,只能
用对象.成员进行访问
4.对于方法中的内部类或块中内部类只能访问块中或方法中的final变量。
类成员有两种static , non-static,同样内部类也有这两种
non-static 内部类的实例,必须在外部类的方法中创建或通过外部类的实例来创建(OuterClassInstanceName.new innerClassName(ConstructorParameter)),并且可直接访问外部类的信息,外部类对象可通过OuterClassName.this来引用
static 内部类的实例, 直接创建即可,没有对外部类实例的引用。
内部类不管static还是non-static都有对外部类的引用
non-static 内部类不允许有static成员
方法中的内部类只允许访问方法中的final局部变量和方法的final参数列表,所以说方法中的内部类和内部类没什麽区别。但方法中的内部类不能在方法以外访问,方法中不可以有static内部类
匿名内部类如果继承自接口,必须实现指定接口的方法,且无参数
匿名内部类如果继承自类,参数必须按父类的构造函数的参数传递
简单的内部类定义形如这样:
class A{
class B{}
}
这样的类被称为内部类,又被称为内隐类. 从简单到深入一步一步的分析内部类的特点。
class OuterClass{ static class A{//静态内部类 public A( ){ System.out.println("Test$A !"); } } class B{//非静态内部类 public B(){ System.out.println("Test$B !"); } }
public void disp( )
{
final int a=10;
int b;
class C
//成员函数中的局部内部类
{
public C( )
{
System.out.println(“in class C a="+a);
//System.out.println(b);
}
}
C c=new C( );
}
}
public class Test extends OuterClass
{
public static void main(String args[])
{
OuterClass.A a=new OuterClass.A();
//建立静态内部类对象
B b=new OuterClass( ).new B();
//建立非静态内部类的对象
//注意这个OuterClass().new B();相当于生成一个外部类的对象,然后在利用外部类对象生成内部类对象
OuterClass t=new OuterClass( );
t.disp( );
//通过外部对象调用一个对象方法的形式,新建立了对象C.
}
}
注意在上面的b在运行时会为0,因为是类属性.
class OuterClass
{
static class A
{
} //静态内部类
class B
{
} //非静态内部类
public void disp( )
{
class C{ } //局部内部类
}
}
编译后的将产生下面的一些类文件:
OuterClass.class
OuterClass$A.class
OutClass$B.class
OuterClass$1$C.class
记住以下几句话:
1,一个内部类的对象能够访问创建它的外部类对象的所有属性及方法(包括私有部分)。
//可以闭上眼镜,把这个内部类等同于一个类的一个方法,当然就可以访问这个外部类的
//所有方法和属性,私有方法和属性是属于外部类的,当然也就等同于内部类的.
2,对于同一个包中的其它类来说,内部类能够隐藏起来。(将内部类用private修饰即可)
//只有在内部类中,才能定义一个为private类型的class,因为这时编译器已经把这个类看作这个类的成员了,但是在一般使用时,就是所谓的”顶级类时”,不能使用private,只能是public 或者是friendly. 如果要是想保证一个类不产生任何的对象,请在构造函数中,把构造函数声明成private.
3,
内部类可定义在方法中,称为局部内部类,但它只能使用方法中的final常量。
// 定义在一个方法内的类,又被成为局部内部类,这个类只能使用在方法中的final常量,注意,这个常量是在一个方法中的,那么能否使用一个类中的常量呢?
当然是可以的,因为类中的常量在在一个方法中是可见的.
//
如果把一个类写在了一个if中,比如这样:
class A{
int a = 10;
if(a!=10){
class B{
B(){
System.out.println(a);
}
}
}
}
在编译后会有几个错误呢?
首先那个a没有被定义为final,你有一次上了圈套. 类B同样会被生成出来,只是离开了if域就失效了.
4,内部类可以被定义为抽象类
//
abstract 类同样可以在内部类中
5,
非静态内部类不能声明本类的static成员
//只有一个静态的内部类,才可以声明一个static成员,
class A{
static
class B{
//如果这里不是一个static类,是不可以被声明这个gg方法的.
static void gg(){
int a = 100;
System.out.println(a);
}
}
}
class aa{
public static void main(String args[]){
A.B hh = new A.B();
hh.gg();
}
}
使用内部类可以非常方便的编写事件驱动程序
这个在写事件驱动时,会有很好的解释.
匿名内部类
在某些情况下,我们只需要内部类的一个对象,那么我们就没有必要给内部类命名,没有名字的内部类我们称为匿名内部类
public class A extends Applet
{
public void init( )
{
addMouseListener( new B( ) );
}
class B extends MouseAdapter
{
public void mousePressed(MouseEvent me)
{
showStatus("Mouse Pressed.");
}
}
}
用匿名内隐类修改:
import java.applet.*;
import java.awt.event.*;
import java.awt.*;
public class AnonymousInnerClassDemo extends Applet
{
public void init( )
{
addMouseListener( new MouseAdapter( )
{
public void mousePressed(MouseEvent me)
{
showStatus("Mouse Pressed");
}
}
);
}
}
下面是一个think in java里的例子
public class Pr{
public Concents cont(){
return new Concents(){
private int i= 11;
public int value (){return i;}
};//这里是有一个逗号
}
}
这个Contents是通过默认的构造函数产生的,匿名类的产生也就是一个新类向上转型到父类的过程.
那么如果一个父类没有一个默认的构造函数,应该什么办呢? 那就只有调用一个super()了.
class noname{
Warpping wrap(int x){
return new Warpping(x){
public int value(){
return super.value()*47;
}
};
}
public static void main(String s[]){
noname p = new noname();
Warpping w = p.wrap(10);
}
}
如果在匿名内部类中用到了外部对象 , 就必须保证这个外部对象是final的 。
public class PP{
public DD dest(final String dest, final float price){
return new DD(){
private int cost;
{
cost = Math.round(price);
if(cost>100)
System.out.println("Over budget");
}
};
}
publc static void main(String []arg){
PP h = new PP();
DD d = h.dest("haha",11.111);
}
}
[[i] 本帖最后由 smileorcry 于 2008-4-24 14:52 编辑 [/i]]
页:
[1]
