什么是内部类?
类的五大成员
- 属性、方法、构造方法、代码块、内部类
内部类即在一个类的里面,再定义一个类。
-
内部类表示的事物是外部类的一部分
-
内部类单独出现没有任何意义
内部类访问特点
- 内部类可以直接访问外部类成员,包括私有
- 外部类要访问内部类的成员,必须创建对象
内部类分类
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
成员内部类
卸载成员位置的,属于外部类的成员
成员内部类可以被一些修饰符所修饰,比如:private,默认,protected,public,static等
在成员内部类里面,JDK16之前不能定义静态变量,JDK16以后才可以
public class Car{ //外部类
String carName;
int carAge;
int carColor;
class Engine{ //成员内部类
String engineName;
int engineAge;
}
}
获取成员内部类对象
- 在外部类中编写方法,对外提供内部类的对象。
- 直接创建格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象
public class Outer{
String name;
class Inner{
//JDK16之后才可以这样书写
static int num = 10;
}
public Inner getInstance(){
return new Inner();
}
}
public class Test{
public static void main(String[] args){
//直接创建内部类对象
//若成员内部类被private修饰,则无法直接创建内部类对象,只能通过在外部类中编写方法,对外提供内部类的对象。
Outer.Inner oi = new Outer.new Inner();
//另一种方法
//若Inner私有,则不能使用 Outer.Inner inner = o.getInstance();
//可以使用Inner的父类创建,形成多态,但这里Inner没有父类,默认继承Object
Object inner = o.getInstance();
//对象地址值
System.out.println(o.getinstance());
}
}
成员内部类如何获取外部类的成员变量
class Outer{
private int a = 10;
class Inner{
private int a = 20;
public void show(){
int a = 30;
//Outer.this 获取了外部类对象的地址值
System.out.println(Outer.this.a); //10
System.out.println(this.a); //20
System.out.println(a); //30
}
}
}
Outer.this.a 的原理:
静态内部类
是成员内部类的一种特殊情况
静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象。
public class Car{ //外部类
String carName;
int carAge;
int carColor;
static class Engine{ //静态内部类
String engineName;
int engineAge;
}
}
获取静态内部类对象
创建静态内部类对象的格式: 外部类名.内部类名 对象名 = new 外部类名.内部类名();
public class Test{
public static void mian(String[] args){
//创建静态内部类的对象
//只要是静态的东西,都可以直接用类名点直接获取
//非静态方法
Outer.Inner oi = new Outer.Inner();
oi.show1();
//静态方法
Outer.Inner.show2();
}
}
public class outer{
int a = 10;
static int b = 20;
static class Inner{
public void show1(){
System.out.println(a); //报错
Outer o = new Outer();
System.out.println(o.a); //正常
System.out.println(b); //正常
System.out.println("非静态的方法被调用");
}
public static void show2(){
System.out.peintln("静态方法被调用");
}
}
}
局部内部类
-
将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。
-
外界是无法直接使用,需要在方法内部创建对象并使用。
-
该类可以直接访问外部类的成员,也可以访问方法内的局部变量。
public class Test{
public static void main(String[] args){
/*
//无法直接使用show方法里面的局部变量a
Outer o = new Outer();
o.a; //这里a指成员变量,无法访问到show方法中的a
*/
Outer o = new Outer();
o.show();
//输出
/*
null
0
10
20
局部内部类中的f1方法
局部内部类中的f2方法
*/
}
}
public class Outer{
int b = 20;
public void show(){
int a = 10;
//局部内部类
//和局部变量类似
class Inner{
String name;
int age;
public void f1(){
System.out.println(a); //正常
System.out.println(b); //正常
System.out.println("局部内部类中的f1方法");
}
public static void f2(){
System.out.println("局部内部类中的f2方法");
}
}
//创建局部内部类对象
Inner i = new Inner();
System.out.println(i.name);
System.out.println(i.age);
i.f1();
Inner.f2();
}
}
匿名内部类
匿名内部类本质就是隐藏了名字的内部类
格式:
new 类名或直接接口名(){
重写方法;
};
代码演示
public class Test{
public static void main(String[] args){
//new 类名();
new Swim(){
@Override
public void swim(){
System.out.println("游泳");
}
};
}
}
public interface Swim{
public abstract void swim();
}
//上文中代码段
{
@Override
public void swim(){
System.out.println("游泳");
};
//表示没有名字的类
//实现了Swim类,所以要重写Swim中的抽象方法
//若Swim为抽象类
//则是没有名字的类继承了Swim类,也要重写Swim中的抽象方法
所以可以得出匿名内部类包含了:
- 继承/实现关系;
- 方法的重写;
- 创建对象。
匿名内部类作用
public class Test{
public static void method(Animal a){
a.eat();
}
//若要调用method方法
//需要先创建一个具体的动物类Dog
Dog d = new Dog;
method(d);
//如果Dog只需要用一次,这种方法过于麻烦
//匿名内部类方法
method(new Animal(){
@Override
public void eat(){
System.out.println("狗吃骨头");
}
});
}
public abstract class Animal{
public abstract eat();
}
public class Dog extends Animal{
@Override
public void eat(){
System.out.println("狗吃骨头");
}
}