前言
内部类的概念:在一个类的内部再定义一个完整的类,内部的类被称为内部类。
思考:为什么我们需要内部类呢?
答:可以类比我们现实生活中,人可以被称为一类,但是人里面,又可以分为科学家、艺术家等等也属于类而非个体。也像是人的身体与器官的关系。
下面通过代码来示范一个简单的例子:
//定义一个外部类
public class Person{
private String name = "尼可乐";
//定义一个内部类
class Scientist{
public void show(){
System.out.println(name);
}
}
}
由上面的例子可以看出,内部类是可以随意访问外部类的私有属性的。那么内部类具有以下特点:
- 内部类可以直接访问外部类的私有成员,而不破坏封装。
- 内部类在编译之后是可以生成独立的字节码文件的。
- 内部类可以为外部类提供必要的内部的组件。
内部类的分类:
- 成员内部类:一个类定义在另一个类中。
- 静态内部类:static修饰的内部类。
- 局部内部类:定义在一个方法内部的类。
- 匿名内部类:没有名字的内部类。(在接口和抽象类中用的较多)
1.成员内部类
在类的内部定义,与实例变量、实例方法同级别的类。
属于外部类的实力部分,创建内部类对象时候,必须依赖外部类对象。
public class Test{
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.show();
}
}
//定义一个外部类
class Outer {
private String name ="尼可乐";
private int age = 20;
//定义一个内部类
class Inner{
private String address = "西安";
private String tel = "123";
private String name = "福腻";
public void show(){
//打印外部类属性
System.out.println(Outer.this.name);
System.out.println(age);
//打印内部类属性
System.out.println(address);
System.out.println(tel);
System.out.println(name);
}
}
}
成员内部类需要注意的点:
-
创建内部类对象时,必须依赖外部类对象
方式一: Outer outer = new Outer(); //实例化外部类对象
Outer.Inner inner = outer.new Inner(); //通过外部类对象来实例化内部类对象方式二:Outer.Inner.inner = new Outer().new Inner(); //一步到位。
-
当外部类、内部类存在重名属性时,会优先访问内部类属性。如果想访问外部类此属性则需要加前传Outer.this.
-
成员内部类不可以定义静态成员(static修饰的成员)。但是可以定义静态常量(static final修饰的属性)。
2.静态内部类
在成员内部类的基础上添加一个static关键字
但是和成员变量不同的是,静态内部类不依赖外部类对象。创建对象时不要通过外部类对象来创建
注意:只有静态内部类可以使用static修饰符修饰,普通类不可以使用static修饰符。
静态内部类级别和外部类相同,不再依赖外部类,主要作用是给外部类提供一些功能。因此内部类中访问外部类则需要先创建一个外部类对象。
public class Test{
public static void main(String[] args) {
Outer.Inner inner = new Outer.Inner();
inner.show();
}
}
//定义一个外部类
class Outer {
private String name ="尼可乐";
private int age = 20;
//定义一个内部类
static class Inner{
private String address = "西安";
private String tel = "123";
//静态属性
private static int count = 100;
public void show(){
Outer outer = new Outer();
//打印外部类属性
System.out.println(outer.name);
System.out.println(outer.age);
//打印内部类属性
System.out.println(address);
System.out.println(tel);
System.out.println(count);
}
}
}
注:在测试类中创建对象时,依旧有前缀Outer,但是我们可以对比静态内部类和成员内部类,这里是没有括号的,翻译成人话就是,外部类的内部类的对象,是由外部类的内部类创建出来的。因此实际上和外部类是没有关系的。并非由外部类对象创建。其他特点和成员内部类相仿就不过多赘述。
3.局部内部类
- 局部内部类是定义在外部类方法中的类,作用范围仅限于所在的方法中。
- 局部内部类不能加任何访问修饰符。
- 局部内部类不能包含任何静态成员,但是可以包含final static修饰的静态常量。
- 局部内部类访问外部类当前方法中的局部变量时,因无法保障生命周期与自身相同,因此局部变量必须用final修饰。(jdk1.8版本开始默认为final修饰,因此可以加也可以不加,但是即使不加也默认是常量。)
- 局部内部类使用的场合较少
public class Test{
public static void main(String[] args) {
//调用局部内部类,则需要在外部类的方法内完成,然后创建外部类的对象,通过对象来调用内部类所在的方法
Outer outer = new Outer();
outer.show();
}
}
//定义一个外部类
class Outer {
//定义外部类属性
private String name ="尼可乐";
private int age = 20;
//定义一个外部类的方法
public void show(){
//定义局部变量(默认final修饰)
String address = "成都";
//定义局部内部类,地位和局部变量一样
class Inner{
private String tel = "123456789";
public void InnerMethod(){
//调用外部类的属性,可以加前缀也可以不加,但是最好加上,可以快速看出这个属性是那个类中的
System.out.println(Outer.this.name);
System.out.println(age);
//调用局部内部类中的属性
System.out.println(tel);
//调用局部变量
System.out.println(address);
}
}
//调用局部内部类的方法则需要通过实例化局部内部类的一个对象来调用,但是他仍在外部类的方法中
Inner inner = new Inner();
inner.InnerMethod();
}
}
4.匿名内部类
匿名内部类可以理解为没有类名的局部内部类(实际上编译器会自动给他曲名),他的一切特征都与局部内部类相同,但是匿名内部类必须通过继承一个父类或者实现一个接口来实现。实际上匿名内部类就是定义类、实现类、创建对象的语法合并,并且只能创建一个该类的对象。
因此当局部内部类只需要使用一次的时候,这种情况下我们可以使用匿名内部类来进行代码优化。
优点是:减少代码量。
缺点:可读性较差。
public class Test{
public static void main(String[] args) {
//匿名内部类通过接口的实现
Usb usb = new Usb(){
@Override
public void service() {
System.out.println("连接电脑成功!");
}
};//要注意这里是有一个分号的。
usb.service();
}
}
//写一个接口
interface Usb{
void service();
}
注:抽象类与父类也可使用这种方法来优化代码。使用匿名内部类然后重写方法,再进行调用就可以了。
好啦,内部类部分就总结到这里啦。