一、内部类的定义和使用
1、内部类定义:
所谓内部类就是在一个类的内部又定义其他类,在结构上形成嵌套关系。
下面定义一个简单的内部类:
class Outter{
private int count = 100;
//定义一个内部类Inner
class Inner{
public void print(){ //定义一个普通方法
System.out.println(count); //调用外部类私有属性
}
}
//在外部类中定义一个方法
public void fun(){
Inner in = new Inner(); //产生内部类对象
in.print(); // 使用内部类提供的print()方法
}
}
public class Demo2{
public static void main(String[] args) {
Outter out = new Outter(); //产生外部类对象
out.fun(); //调用外部类方法
}
}
可以看到,内部类虽然可以方便的调用外部类的私有属性,但是,引入内部类后,程序的结构有些混乱。
2、如何创建类对象:
1) 在使用内部类的时候创建内部类对象:
外部类.内部类 内部类对象 = new 外部类().new 内部类();
Outter.Inner in = new Outter().new Inner();
2) 在外部类内部创建内部类对象:
Inner in = new Inner();
3) 在外部类的外部创建对象:
外部类.内部类 内部类对象 = new 外部类.内部类();
Outter.Inner in = new Outter.Inner();
3、为什么使用内部类:
1) 内部类方法可以访问该类定义所在作用域中的属性,包括被 private 修饰的私有属性
2) 内部类对同一包中的其他类来说是隐藏的
3) 内部类可以解决 java 单继承的缺陷
4) 当想要定义一个回调函数却不想写大量代码的时候,我们可以选择使用匿名内部类来实现
示例:使用内部类实现多继承
class A{
public void funcA() {
System.out.println("类A的方法");
}
}
class B{
public void funcB() {
System.out.println("类B的方法");
}
}
class Outter{
class InnerClassA extends A{
public void printA(){
super.funcA();
}
}
class InnerClassB extends B{
public void printB(){
super.funcB();
}
}
public void print(){
new InnerClassA().printA();
new InnerClassB().printB();
}
}
public class Demo2{
public static void main(String[] args) {
Outter out = new Outter();
out.print();
}
}
4、内部类与外部类有什么关系:
1) 对于非静态内部类,内部类的创建依赖外部类的实例对象,在没有外部类实例之前是无法创建内部类的。
2) 内部类是一个相对独立的实体,与外部类不是is-a关系。
3) 内部类可以直接访问外部类的属性(包含私有属性),但是外部类不可以直接访问内部类的属性。
4) 外部类可以通过内部类引用,间接访问内部类属性。
5、java中内部类的分类:
1) 实例内部类(成员内部类)
2) 静态内部类
3) 局部内部类(方法内部类)
4) 匿名内部类
二、内部类详解
1、实例内部类(成员内部类):
需要注意两点:
1)成员内部类中不能存在任何static的变量和方法。
2)成员内部类是依附于外部类的,所以只有先创建外部类后才能够创建内部类。
2、静态内部类:
使用static修饰的内部类我们称之为静态内部类。
静态内部类与非静态内部类之间最大的区别,在于非静态内部类在编译完成之后会隐含地保存一个引用,该引用是指向创建它的外部类,但是静态内部类却没有,因此:
1)静态内部类对象的创建不需要依赖于外部类,可以直接创建
2)静态内部类不可以使用任何外部类的非static成员属性和方法
示例:创建静态内部类
class Outter{
static class Inner{
public void print(){
System.out.println("内部类print方法");
}
}
public void func(){
//静态内部类对象的创建不需要依赖于外部类
Inner inner = new Inner();
inner.print();
}
}
public class Demo2{
public static void main(String[] args) {
Outter out = new Outter();
out.func(); //外部类对象调用静态内部类方法
}
}
3、局部内部类(方法内部类):
方法内部类定义在外部类的方法中,方法内部类和成员内部类基本一致,只是它们的作用域不同,方法内部类只能在该方法中被使用,出了该方法就会失效。
1) 方法内部类不允许使用访问权限修饰符, public private protected 等均不允许。
2) 方法内部类对外完全隐藏,除了创建这个类的方法可以访问它,其他均不允许访问。
3) 方法内部类如想要使用方法形参,该形参必须用final声明(JDK8形参变为隐式final声明)。
4、匿名内部类:
匿名内部类其实就是一个没有名字的方法内部类,所以它符合方法内部类的所有约束。另外需要注意:
1)匿名内部类是没有访问修饰符的。
2)匿名内部类必须继承一个抽象类或者实现一个接口
3)匿名内部类中不能存在任何静态成员或方法
4)匿名内部类是没有构造方法的,因为它没有类名
5)与方法内部类相同,匿名内部类也可以引用方法形参。此形参也必须声明为 final
三、总结:
1、内部类的使用暂时不作为设计的首选,内部类具有如下特点:
1)内部类的使用破坏了程序的结构。
2)内部类能方便的访问外部类私有属性。(外部类也可以访问内部类的私有属性)
3)如果发现类名称上出现了 . 符号,应当立即想到是使用了内部类的概念。
2、内部类相关问题:
问题1:实例内部类对象能否定义static的数据成员?
能,使用final的数据成员,是可以在编译期间确定的值。
问题2:实例内部类对象是否有额外的内存消耗?
有,实例内部类拥有外层类的this引用。
问题3:静态内部类能否访问外部类的实例数据成员?
能,外部类拿到对象,传给内部类。