您的位置:首页 > 编程语言 > Java开发

java内部类学习与总结

2016-02-18 23:06 591 查看
我们经常会看到诸如此类的代码:

class A {
double i = 0;

public Circle(double radius) {
this.i = i;
}

class B {     //内部类
public void print() {
System.out.println("这是内部类");
}
}
}


在java中,我们称它为内部类,顾名思义就是在一个类的内部再写一个类的形式,内部类是一种非常有用的特性,它允许你把一些逻辑相关的组织在一起,并控制位于内部类的可视性。

内部类的分类:

常规内部类

静态内部类

匿名内部类

局部内部类

我们先从最简单的常规内部类说起介绍起吧~

常规内部类

代码如下所示:

public class Outter {
class Inner{
int i;
public Inner() {
i=1;
System.out.println("Inner内部类产生了");
}

}
public Outter() {
System.out.println("Outter外部类产生了");
}
}

********
Outter outter=new Outter();
Outter.Inner inner=outter.new Inner();
//Outter.Inner in=new Outter().new Inner()也可以实现上述相同的效果


输出结果:



这里进行说明:当我们需要去掉用常规内部类的时候,我们需要通过如下的格式去调用:OutterClassName.InnerClassName,好了,用法介绍完毕了,但是你可能会问为什么要用内部类,我在外部类中不一样也可以实现内部类的功能么?

考虑这样的一种情况,当我的一个类要实现接口的时候,我又不想把这个接口公开出来,那该怎么做呢?这时候我们就可以使用内部类进行处理,看代码:

//接口
public interface PrivateMethod {
void cout();
}
*****
public class Outter {
class Inner implements PrivateMethod{
int i;
public Inner() {
i=1;
System.out.println("Inner内部类产生了");
}
@Override
public void cout() {
System.out.println("我不想让别人知道Outter实现PrivateMethod接口");

}

}
public Outter() {
System.out.println("Outter外部类产生了");
}
}
****
{
Outter outter=new Outter();
Outter.Inner inner=outter.new Inner();
inner.cout();
}


结果如下图所示:



这里我们可以看到,我们隐藏了PrivateMethod这个接口对于Outter的实现细节,相当于private修饰符的作用,保证了我们代码不对外公开,只提供实现,很好的保护了代码的安全性。

注意:普通的类(非内部),不能声明为private或者protected,他们只可以被赋予public或者默认包的访问权限。

匿名内部类

代码如下图所示:

public PrivateMethod newInstance(){
return new PrivateMethod() {

@Override
public void cout() {
System.out.println("我是匿名内部类");

}
};
}
*****main中的代码
Outter outter=new Outter();
//      Outter.Inner inner=outter.new Inner();
//      inner.cout();
outter.newInstance();


我们可以看到结果显示:



在这里我们通过一个方法(其返回值是接口类型),返回了一个接口实现,但是我们可以看到,在其中我们并没有定义一个变量,而是直接通过new PrivateMethod的形式去实现。关于匿名内部类,在android中,我们经常可以看到:

iv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {

}
});


这就是一个比较常规的实现,关于匿名类,就介绍道这里。

静态内部类(内嵌内部类)

一般而言(除了静态内部类),内部类都会保存一个”隐藏”的应用去指向外部类,如果我们不需要引用,也就是内部类的实现与外部类无关,我们可以定义成static class,定义完后就意味着:

1.要创建嵌套类,并不需要其外部类的对象

2.不能从嵌套类的对象中访问非静态的外围类对象

嵌套类还跟常规内部类有一个区别,常规类的字段与方法中,不能放在嵌套类中,反之,也成立。

Outter.class

public static  void say(){
System.out.println("静态内部类");
}
}
******
Outter.staticMethod.say();


我们在Outter.class添加上述代码,在主方法中直接调用Outter.staticMethod.say(),就产生如下的结果:



局部内部类

典型的局部内部类是在一个方法体中创建,局部内部类不能有访问说明符,因为他不是外部类的一部分,但是它可以访问当前代码块的常量以及外围类的所有成员:

//接口类
public interface MyInterFace {
void getJuBu();
}

//外部类

public class Outter2 {
MyInterFace getInstance(){
class InnerJuBu implements MyInterFace{
@Override
public void getJuBu() {
System.out.println("这是局部内部类的实现");
}
}
return new InnerJuBu();
}
}
//主方法
Outter2 outter2=new Outter2();
outter2.getInstance();


实现结果:



我们在getInstance()方法中实现了一个返回值为InnerJuBu的内部类,最终向外传递这个内部类,实现类局部内部类的调用。

关于内部类的继承:

因为内部类的构造器必须连接到指向其外部类对象的引用,所以在继承内部类的时候,事情会变得有些复杂,主要在于,必须要让秘密的引用初始化,详细的代码如下图所示:

public class Outter2 {
class Inner{

}
}


public class InnerExtends extends Outter2.Inner {
public InnerExtends(Outter2 outter) {
outter.super();
}

}


我们看到如果要继承一个内部类,必须要首先继承Outter2.Inner这个内部类,然后我们在其构造函数中调用outter.super()方法,这样就可提供内部类必要的引用,程序才会编译通过。

内部类是否被覆盖:

class Out{
protected class In{
}
}

class Demo extends Out{
public class In{
}
}


如同上述代码,即是我们在Demo中写了In类,java会认为这是一个全新的类,并不认为这是从父类,也就是Out这个类中继承过来的,如果要继承,应该通过如下的方式:

class Out{
protected class In{
}
}

class Demo extends Out {
public class In extends Out.In{
}
}


通过继承的方式,我们去重载相关方法实现覆盖。

内部类标识符:

由于每个类都会产生一个.class文件,其中包含了如何创建该类型的对象的全部信息(此信息产生一个”meta-class”,叫做class对象),内部类也必须产生一个.class文件包含他们的class信息,这些类文件有严格的规则:外部类的名字,加上”$”,再加上内部类的名字如:

class Out{
protected class In{
}
}


编译过后则会产生一个Out.class文件以及一个Out$In.class文件,如果内部类是匿名的,则会简单的产生一个数字作为标识符,如Out$1.class

为什么需要内部类:

一般来说,内部类继承了某个类或实现某个接口,内部类操作外部类的对象,所以可以认为是内部类提供了某种进入外围类的窗口。

内部类最重要的原因是:

每个内部类都能独立继承一个(接口的)实现,无论外围伦是否已经继承了某个(接口的)实现,对于内部类来说都没有影响。

我们可以借助内部类实现多重继承(若拥有的是抽象或者具体的类,而不是接口)

如:

class D{}
abstract class E{}

class Z extends D{
E makeE(){
return new E();
}


参考文献及资料:

1.《java编程思想》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: