前言
当⼀个事物的内部,有时候比较复杂的话,内部需要一个完整的结构来描述,这个内部的一个完整结构可以最好使用内部类
在Java中,可以将⼀个类定义在另⼀个类,被称为内部类,内部类也是封装的⼀种体现
内部类
内部类可以分为实例内部类、静态内部类、局部内部类和匿名内部类
class Outclass{
//实例内部类
//定义类中的普通类
public class innerclass1{
}
//静态内部类
//定义类中的静态类
static class innerclass2{
}
//局部内部类
//定义方法中
public void method(){
class innerclass3{
}
}
}
1 实例内部类
实例内部类就是在一个类中没有被static修饰的普通内部类
class Outcalss {
public int a = 10;
public int b = 20;
//实例内部类
class Innerclass{
public int a = 100;
public void method(){
System.out.println(a);
}
}
}
public class Test {
public static void main(String[] args) {
Outcalss outcalss = new Outcalss();
System.out.println(outcalss.a);
System.out.println(outcalss.b);
}
}
运行结果如下
上面可以创建外部类的对象,访问的是内部类外面的成员,如何访问内部类的变量和方法呢,这时候需要创建内部类的对象,请看下面
//第一种
外部类.内部类 内部类对象名 = new 外部类().new 内部类();
//第二种
外部类 外部类对象 = new 外部类
外部类.内部类 内部类对象名 = 外部类对象.new 内部类();
//外部类创建
Outcalss outcalss = new Outcalss();
//内部类创建
//创建外部类的同时创建内部类
Outcalss.Innerclass innerclass1 = new Outcalss().new Innerclass();
//先创建好外部类,在创建内部类
Outcalss.Innerclass innerclass2 = outcalss.new Innerclass();
可以看到我们结合上面的类,进行创建了两个内部类对象,这里有两种方式,更推荐第二种。我们也可以知道,内部类相当于外部类中的一个成员,如果想要访问内部类,肯定要先创建外部类对象,才可以创建内部类对象
class Outcalss {
public int a = 10;
public int b = 20;
public int c = 30;
class Innerclass{
public int a = 100;
//在内部访问外部的相同变量
public void method(){
Outcalss.this.a = 11;
System.out.println(Outcalss.this.a);
}
}
}
public class Test {
public static void main(String[] args) {
Outcalss outcalss = new Outcalss();
System.out.println(outcalss.a);
System.out.println(outcalss.b);
System.out.println("========================");
//创建外部类的同时创建内部类
Outcalss.Innerclass innerclass1 = new Outcalss().new Innerclass();
//现创建好外部类,在创建内部类
Outcalss.Innerclass innerclass2 = outcalss.new Innerclass();
//调用内部类成员变量和方法
System.out.println(innerclass2.a);
innerclass2.method();
}
}
运行结果如下
这里不仅可以使用外部类访问内部类成员变量和函数,也可以在内部类中访问外部类成员
这里在内部类中使用 外部类名.this.成员来访问
1.外部类中的任何成员可以在实例内部类中通过 外部类名.this 直接访问
2.实例内部类也受public、private等修饰限定符限制
3.实例内部类对象相当于外部类的一个成员,因此实例内部类对象必须先创建外部类对象
4.内部类方法中访问与外部类相同的变量的时候,会优先访问自己的,如果像访问外部的要外部类名.this.变量名
2 静态内部类
静态内部类:被static修饰的内部成员类
静态内部类的创建对象和实例内部类不同,静态内部类直接创建内部类对象,不需要像实例内部类那样先创建外部类对象,在创建内部类对象
//静态内部类对象创建
外部类.内部类 内部类对象名 = new 外部类.内部类
OutClass.Innerclass innerclass = new OutClass.Innerclass();
例如:
class OutClass{
public int a;
public static int b;
static class Innerclass{
public void method(){
//不可以访问外部类的非静态成员
//但可以访问静态成员
//a = 20;
b=30;
System.out.println(b);
}
}
}
public class Test {
public static void main(String[] args) {
OutClass.Innerclass innerclass = new OutClass.Innerclass();
innerclass.method();
}
}
运行结果如下
静态内部类中可以直接访问外部类中的静态成员,不可以直接访问非静态成员
就像下面这样访问非静态的成员,编译器会报错
如果非要访问,可以在内部类中创建一个外部类对象访问
class OutClass{
public int a;
public static int b;
static class Innerclass{
public void method() {
//不可以直接访问外部类的非静态成员
//但可以访问静态成员
//创建外部类对象进行访问
OutClass outClass = new OutClass();
System.out.println(outClass.a);
b = 30;
System.out.println(b);
}
}
}
public class Test {
public static void main(String[] args) {
OutClass.Innerclass innerclass = new OutClass.Innerclass();
innerclass.method();
}
}
运行结果如下
1.静态内部类中可以直接访问外部类中静态成员,但不能直接访问外部类中的非静态成员
如果想访问,需要创建外部类对象进行访问
2.创建内部类对象时,不需要先创建外部类对象,可以直接创建内部类对象
3 局部内部类
局部内部类:在外部类的⽅法体或者{ }代码块中,只可以在其定义的位置使用,这里实例化局部内部类对象,也是必须在其定义的地方
class Outclass{
public int a;
public void method() {
int b = 20;
//局部内部类创建在外部类的方法中
//不可以被public、static等访问限定修饰符修饰
class Innerclass {
public void methodInclass() {
System.out.println(a);
System.out.println(b);
}
}
//创建内部类对象
Innerclass innerclass = new Innerclass();
//访问局部内部类中的方法
innerclass.methodInclass();
}
}
public class Test {
public static void main(String[] args) {
Outclass outclass = new Outclass();
outclass.method();
}
}
运行结果如下
这里的局部内部类不可以被public 、static等访问限定修饰符修饰
就像下面这样编译器直接报错
1.局部内部类只能在其所定义的方法体的内部进行创建对象和使用
2.局部内部类不可以被public、static等访问限定修饰符修饰
4 匿名内部类
匿名内部类:其实其实是一种特殊的嵌套,没有类名,在声明的同时进行实例化
相当于对接口的实现、继承父类等等,实现接口或者重写父类方法
new SuperType(constructor-arguments) {
//接口/抽象类/具体类
};
实现接口中的匿名内部类
//接口
interface Get{
//接口不可以有方法主题
void getting();
}
public class Test {
public static void main(String[] args) {
//匿名内部类的创建和使用
Get get = new Get() {
@Override
public void getting() {
System.out.println("hello world");
}
};
//使用
get.getting();
}
}
运行结果如下
继承父类中的匿名内部类
//父类
class Get{
void getting(){
}
}
public class Test {
public static void main(String[] args) {
Get get = new Get() {
//也可以正常创建对象和访问
public static int a = 10;
@Override
public void getting() {
a=20;
System.out.println(a);
System.out.println("hello world");
}
};
get.getting();
}
}
在匿名内部类中也可以匿名内部类当中可以定义和正常类⼀样的成员变量,但是在 @Override上面不可以有可执行程序,就像赋值操作不可以,如果有编译器会报错
匿名内部类没有访问权限修饰符
匿名内部类是继承父类或者实现接口,对其中的方法进行重写
在匿名内部类中重写方法上面不可以有可执行程序,例如:赋值操作
匿名内部类以分号;结尾