Java 内部类

来源:互联网 发布:mac 大容量网盘 编辑:程序博客网 时间:2024/06/11 03:01

工作半年多的经历中,内部类的使用虽然不多,但是很多设计都需要它。例如SE部分的集合中,HashMap、LinkedList等都离不开内部类的支持。那么今天就在之前泛泛而学的基础上在进行一次较为深入的内部类基础学习。废话不多说,开始学习了。


一、什么是内部类?

内部类,其实就是将一个类定义在一个常规类的内部。

它可以定义在外部类作用域,即和外部类的方法、成员变量同级,我姑且成为普通内部类,也可以定义在方法内部,甚至if代码块内部,称为局部内部类。

内部类内部可以继续定义内部类无限嵌套。

public class OutterClassTest {
private int outerVariable = 0;
//内部类
class InnerClass{
private Integer innerVariable = 11;
public Integer getInnerVariable(){
return innerVariable;
}
//内部类的内部类
class Inner{

}
}
public void a(){
if(1==1){
//方法内部类
class inner1{

}
}
}
}

二、内部类的作用域(非常重要)

1、普通内部类的作用域:同普通的其他类一样,根据访问修饰符确定的。如上方的内部类,default的可以被本包的任何类访问。

package innerClass;
import innerClass.OutterClassTest.InnerClass;
public class Test {
public static void main(String[] args) {
InnerClass in = new OutterClassTest().new InnerClass();
}
}

如果是private 修饰的话,只能被该外部类的对象访问。似乎看起来和其他类没有什么不同,只是初始化该对象的语法有些区别罢了。

2、局部内部类的作用域:和局部变量一样,只能在该域内被访问,如上方的方法内部类,出了if代码块,便不能访问到该类了。

public void a(){
if(1==1){
//方法内部类
class inner1{
}
sinner1 in1 = new inner1();
}
}

3、内部类可以无条件的、毫无阻碍的访问外部类的属性、方法。

三、创建内部类的对象

1、在外部类的非静态方法创建内部类对象,和普通类一样简单:

public   void t(){
InnerClass in =new InnerClass();
}

2、在外部类的静态方法中创建内部类对象,如main等方法,需要实例化的外部类对象来访问并创建对象

public static void main(String[] args) {

//通过外部类的实例化对象来new 内部类的对象
InnerClass in = new OutterClassTest().new InnerClass();
}

注意语法。

3、.this与.new 的使用:.this 使用外部类的类名.this,返回外部类的对象

使用外部类的对象.new 内部类名(),实例化该外部类对象的内部类对象

public InnerClass getInner(){
return OutterClassTest.this.new InnerClass();
}


四、内部类的向上转型

1、和其他类一样,内部类可以继承其他可以被继承的任何类,所以在实例化对象后可以向上转型为父类,在其他类形成该内部类的具体引用而很好隐藏了实现细节。

2、和其他类一样,内部类可以实现任何接口,所以在实例化对象后可以向上转型为接口类,在其他类形成该内部类的具体引用而很好隐藏了实现细节。


五、匿名内部类

//创建一个线程并实线run方法并开始执行
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("----");
}
}).start();

如上方代码,就是一个匿名内部类。Thread需要一个实现Runable接口的对象为参数,然而并没有创建一个类去实现该接口,而是直接new 并立即实现了该接口,所以虽然该接口被实现了,但是实现该接口的类却是没有具体的名字的,我们将这种使用方法称之为匿名内部类。

所以,匿名内部类是指:创建一个继承自某个父类或者实现了某个接口的对象并立即实现接口,而不去新建一个类并继承或实现该接口,再new需要的对象。


六、关于静态内部类与非静态内部类

1、普通内部类对象默认隐藏的保存了一个引用,其指向外部类的对象。(非static修饰),而静态内部类没有保存该引用。所以:

创建静态内部类的方法不需要像普通内部类那样,使用外部类的对象来创建,静态内部类的对象可以直接创建:

public class OutterClassTest {

static class Inner1{
}
public static void main(String[] args) {
//直接创建静态内部类对象
Inner1 in1 = new Inner1();
}
}

如上,不用使用OutterClassTest.this.new Inner1()!!

其次:静态内部类的对象不能方法外部类中非静态的变量。

public class OutterClassTest {
int a = 1;
static int b = 2;
static class Inner1{
//报错
int c = a;
//正常
int d = b;
}
}

2、静态内部类可以使用static修饰属性和方法,而普通的内部类不能使用static修饰属性和方法。

static class Inner1{
//静态内部类编译正常
static int f = 0;
}
class Inner2{
//普通内部类f编译报错
static int f = 0;
}

七、内部类的特性:

1、内部类可以有很多实例,每个实例有自己的状态信息,并且与外围的类对象是互相独立。

2、单个外围类中可以让多个内部类继承多个父类,实现java不能多种继承的问题。

3、创建内部类的对象的时刻并不一定依赖与外部类的对象才能创建。

4、内部类和外部类的关系不是“is-a”关系,他们是独立的个体。

八、一些有趣的问题:

1、内部类的继承问题,即内部类继承内部类:因为内部类的构造器默认指向外围类的对象引用,继承后需要重写默认构造器,入参外类类对象并调用super();可以实现

将继承后的构造器指向外围类的对象。

2、如果创建内部类继承外围类并重写了外围类的一个内部类,父类的内部类会被覆盖吗?答案是不会。这两个类是独立的,在自己的命名空间内。

阅读全文
0 0
原创粉丝点击