Java四种内部类
内部类
-
一个类的内部里面又完整的嵌套了另一个类的内部结构,被嵌套的类称为内部类
-
内部类最大的特点就是:可以直接访问私有属性,并且可以体现类与类之间的包含关系
-
基本语法
class outer{ //外部类
private int n1 = 100;
public outer(int n1) {
this.n1 = n1;
}
public void m1(){
System.out.println("m1方法");
}
{
System.out.println("代码块");
}
//内部类
class Inner{
}
} - 局部内部类
特点:
-
1.局内内部类是定义在外部类的局部位置,通常是定义在方法中,也可以定义在代码块内
-
2.局部内部类可以直接访问外部类的所有成员,包括私有的
-
3.局部内部类不可以有访问修饰符,但是可以使用final进行修饰
-
4.作用域:仅仅在他定义的方法或者代码块中
-
5.外部类在方法中,可以创建Inner02对象,然后直接调用方法即可
-
6.外部其他类不能访问局部内部类,因为局部内部类是成员变量
-
7.如果外部类和局部内部类成员重名时,默认遵守就进原则,如果想访问外部类的成员可以使用 this.外部成员进行访问
public class LocalInnerClass {
public static void main(String[] args) {
//6.外部其他类不能访问局部内部类,因为局部内部类是成员变量
outer2 outer2 = new outer2();
outer2.m1();
}
}
class outer2{ //外部类
private int n1 = 100;
private void m2(){
System.out.println("m2方法");
}
public void m1(){
//1.局内内部类是定义在外部类的局部位置,通常是定义在方法中,也可以定义在代码块内
//3.局部内部类不可以有访问修饰符,但是可以使用final进行修饰
//4.作用域:仅仅在他定义的方法或者代码块中
//final class Inner02{
class Inner02{//局部内部类 本质仍然是一个类
private int n1 = 80;
//2.局部内部类可以直接访问外部类的所有成员,包括私有的
public void f1(){
System.out.println(n1);
System.out.println(outer2.this.n1);
System.out.println(this.n1);
m2();
//7.如果外部类和局部内部类成员重名时,默认遵守就进原则,如果想访问外部类的成员可以使用 外部类名.this.外部成员进行访问
}
}
//5.外部类在方法中,可以创建Inner02对象,然后直接调用方法即可
Inner02 inner02 = new Inner02();
inner02.f1();
class Inner03 extends Inner02{
}
}
//代码块中定义内部类
//{
// class Inner02{
// //2.局部内部类可以直接访问外部类的所有成员,包括私有的
// public void f1(){
// System.out.println(n1);
// }
// }
//}
} 2.匿名内部类
-
匿名内部类也是一个类的定义,同时它本身也是一个对象,因此从语法上看。它既有定义类的特征,也有创建 对象对的特征
-
可以直接访问外部类的所有成员,包含私有的
-
不能添加访问修饰符,它的本质其实是一个局部变量
-
不能添加访问修饰符,它的本质其实是一个局部变量
-
作用域:仅仅在它定义的代码块中 外部其他类不能访问匿名内部类,因为匿名内部类是成员变量 如果外部类和匿名内部类成员重名时,默认遵守就进原则,如果想访问外部类的成员可以使用 this.外部成员进行访问
public class AnonymousClass {
public static void main(String[] args) {
outer03 outer03 = new outer03();
outer03.m1();
}
}
class outer03{
private int n1 = 100;
public void m1(){
//基于接口的匿名内部类
//使用IAn接口创建对象 在开发中我们只使用一次这个对象 所以创建对象有点浪费
//Tiger tiger = new Tiger();
//tiger.cry();
//解决方法:使用匿名内部类创建对象
// tiger 的编译类型 ? IA
// tiger 的运行类型 ? 就是匿名内部类 Outer04$1
// jdk 底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1 实例,并且把地址返回给tiger
// 匿名内部类只能使用一次,就不能在使用
IAn tiger = new IAn(){
@Override
public void cry() {
System.out.println("tiger的cry方法");
}
};
tiger.cry();
System.out.println("tiger的运行类型"+ tiger.getClass());
//基于类的匿名内部类
Father father = new Father(){
@Override
public void test() {
System.out.println("重写了father的test方法");
}
};
father.test();
//基于抽象类的匿名内部类
Animal animal = new Animal(){
@Override
void test() {
System.out.println("重写了animal的test方法");
}
};
animal.test();
}
}
//接口
interface IAn{
//cry方法
void cry();
}
//class Tiger implements IAn{
//
// @Override
// public void cry() {
//
// }
//}
class Father{
private int n1 = 100;
public void test(){
}
}
abstract class Animal{
private int n1 = 100;
abstract void test();
} 3.成员内部类 特点:
-
可以直接访问外部类得成员,包括私有得
-
成员内部类可以添加访问你修饰符(private,default,protected,public)
-
作用域:在外部类得类体中如果外部类和成员内部类成员重名时,默认遵守就进原则,如果想访问外部类的成员可以使用 this.外部成员进行访问
public class MemberInnerClass { public static void main(String[] args) { Outer outer = new Outer(); outer.test(); //外部类访问成员内部类 Outer.Inner03 inner03 = outer.new Inner03(); inner03.say(); } } class Outer{ private int n = 100; //成员内部类可以访问所有的成员 包括私有的 //成员内部类可以添加访问你修饰符(private,default,protected,public) //作用域:在外部类得类体中 class Inner03{ public void say(){ System.out.println(n); System.out.println("成员内部类方法"); } } public void test(){ Inner03 inner03 = new Inner03(); inner03.say(); } }
4.静态内部类
特点:
- 可以直接访问外部类得非静态成员,包括私有的
- 可以添加任意的修饰符(private等等)
- 作用域:同其他成员,为整个类体
-
如果外部类和静态内部类成员重名时,默认遵守就进原则,如果想访问外部类的成员可以使用 外部类名.成员进行访问
public class StaticInnerClass {
public static void main(String[] args) {
Outer10.Inner10 inner10 = new Outer10.Inner10();
inner10.say();
}
}
class Outer10 {
private int n1 = 10;
private static String name = "张三";
private static void cry() {
}
//Inner10 就是静态内部类
// 1. 放在外部类的成员位置
// 2. 使用 static 修饰
// 3. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
// 4. 可以添加任意访问修饰符(public、protected 、默认、private),因为它的地位就是一个成员
// 5. 作用域 :同其他的成员,为整个类体
static class Inner10 {
private static String name = "1111";
public void say() {
//如果外部类和静态内部类的成员重名时,静态内部类访问的时,
// 默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.成员)
System.out.println(name + " 外部类 name= " + Outer10.name); cry();
}
}
}
查看3道真题和解析