
内部类的分类:实例化内部类,静态内部类,局部内部类和匿名内部类
public class OutClass {
// 成员位置定义:未被static修饰 --->实例内部类
public class InnerClass1{
}
// 成员位置定义:被static修饰 ---> 静态内部类
static class InnerClass2{
}
public void method(){
// 方法中也可以定义内部类 ---> 局部内部类:几乎不用
class InnerClass5{
}
}
}内部类的基本概念:一个类的内部又完整地嵌套了另一个类结构,则被嵌套的类成为内部类(inner class),嵌套其他类的类称为外部类(outer class)。
class Outerclass { // 外部类
class Innerclass { // 内部类
}
}
class Otherclass { // 外部其他类
}
实例化内部类成员位置定义:未被static修饰 --->实例内部类
实例化实例内部类:
//第一种写法
Outerclass outclass = new Outerclass();
Outerclass.InnerClass innerClass = outclass.new InnerClass();
第二种写法
Outerclass.InnerClass innerClass = new Outerclass().new InnerClass();内部类成员方法能访问外部类的成员变量和方法 内部类访问外部类的成员:
class Outerclass {
public int a = 1;
private int b = 2;
public void method() {
System.out.println("外部类成员方法");
}
class InnerClass {
int c = 10;
public void methodInner() {
System.out.println(a);
System.out.println(b);
System.out.println(c);
method();
}
}
public static void main(String[] args) {
Outerclass outclass = new Outerclass();
Outerclass.InnerClass innerClass = outclass.new InnerClass();
//第二种写法
//Outerclass.InnerClass innerClass = new Outerclass().new InnerClass();
innerClass.methodInner();
}
}
当内部类成员变量与外部类的成员变量名字相同时应该先访问自己内部类的成员变量 若要访问外部类则需要通过:
class Outerclass {
public int c = 100;
public void method() {
System.out.println("外部类成员方法");
}
class InnerClass {
char c = 'a';
public void methodInner() {
System.out.println(c);
method();
}
}
public static void main(String[] args) {
Outerclass outclass = new Outerclass();
Outerclass.InnerClass innerClass = outclass.new InnerClass();
//第二种写法
//Outerclass.InnerClass innerClass = new Outerclass().new InnerClass();
innerClass.methodInner();
}
}
方法一:
System.out.println(Outerclass.this.c);方法二:
Outerclass outerclass = new Outerclass();
System.out.println(outerclass.c);在内部类定义main方法不能运行
用 $ 区分内部类和外部类来命名

class Outerclass {
int a = 1;
public int c = 100;
public void method() {
System.out.println("外部类成员方法");
}
class InnerClass {
char c = 'a';
public void methodInner() {
System.out.println(a);
method();
//访问与内部类成员变量名形同的外部类成员变量
//方法一:
Outerclass outerclass = new Outerclass();
System.out.println(c);
System.out.println(outerclass.c);
//方法二
System.out.println(Outerclass.this.c);
}
}
public static void main(String[] args) {
//实例化 实例内部类
Outerclass outclass = new Outerclass();
Outerclass.InnerClass innerClass = outclass.new InnerClass();
//第二种写法
//Outerclass.InnerClass innerClass = new Outerclass().new InnerClass();
innerClass.methodInner();
}
}

成员位置定义:被static修饰 ---> 静态内部类
实例化静态内部类
Outerclass.StaticInnerclass staticInnerclass = new Outerclass.StaticInnerclass();静态内部类方法只能访问外部类的静态的成员变量和方法,非静态变量和方法不能直接访问 可以通过实例化外部类再进行访问
Outerclass outerclass = new Outerclass();
System.out.println(outerclass.a);如果外部类中的成员和静态内部类中的成员重名时,内部类访问该成员默认遵循就近原则;在静态内部类中想访问外部类的同名成员,使用 外部类名.成员 访问(静态内部类中不能使用 this 关键字)
class Outerclass {
static int c = 111;
//此时外部类的成员变量必须是static修饰
static class StaticInnerclass {
static int c = 100;
public void methodStaticInner() {
System.out.println(c);
System.out.println(Outerclass.c);
}
}
}class Outerclass {
public int a = 1;
private int b = 2;
static int c = 111;
public void method() {
System.out.println("外部类成员方法");
}
static void method1() {
System.out.println("外部类静态成员方法");
}
static class StaticInnerclass {
int a = 100;
public void methodStaticInner() {
System.out.println(c);
method1();
//System.out.println();
//System.out.println(b); 只能访问外部类的static修饰的成员
}
}
public static void main(String[] args) {
//访问外部类的非静态方法
Outerclass outerclass = new Outerclass();
System.out.println(outerclass.a);
outerclass.method();
//实例化静态内部类
Outerclass.StaticInnerclass staticInnerclass = new Outerclass.StaticInnerclass();
staticInnerclass.methodStaticInner();
}
}
实例化内部类(非静态内部类)与外部类实例紧密相关。这意味着非静态内部类可以访问外部类的所有成员(包括私有成员),因为它们持有外部类的隐式引用。此外,非静态内部类可以有非静态成员(方法和属性),这使得它们能够更灵活地与外部类进行交互。然而,实例化内部类的一个限制是它们必须依赖于外部类的实例才能被创建。
静态内部类则与外部类实例没有直接关联,它们可以独立于外部类对象而存在。静态内部类可以使用static关键字来修饰,这意味着它们可以访问外部类的静态成员,但不能直接访问非静态成员。静态内部类的一个主要优势是它们可以在没有外部类实例的情况下被创建和实例化,这使得它们在某些情况下更加灵活和方便。

用法一:实现接口的匿名内部类
interface IA {
public void run();
}
class Outer {
public void OuterMethod() {
//实现接口的匿名内部类
IA tiger = new IA() {
@Override
public void run() {
System.out.println("tiger用四条腿跑");
}
};//内部类创建完毕
System.out.println("tiger的运行类型=" + tiger.getClass());
tiger.run();// tiger对象 可以一直使用
tiger.run();
}
}
public class Test2 {
public static void main(String[] args) {
Outer outer = new Outer();
outer.OuterMethod();
}
}1.需求: 想实现IA接口,并创建对象 2.传统方式,是写一个实现接口的类,实现该接口,并创建该类对象 3.可要求是:该类只是使用一次,后面再不使用; 4. 可以使用匿名内部类来简化开发 5. tiger的编译类型是: IA接口 6. tiger的运行类型是: 就是匿名内部类 Outer$1 (jdk分配的类名,不能使用)
底层分配 类名 Outer$1 ,如下:
class Outer$1 implements IA {
@Override
public void run() {
System.out.println("");
}
}7. jdk底层在创建匿名内部类 Outer1,并立即就创建了 Outer1 实例对象, 并且把对象地址返回给 tiger;
8. 匿名内部类 Outer$1 使用一次后,就不能再使用,但其对象 tiger可以一直使用。
用法二:继承父类的匿名内部类 继承抽象类的匿名内部类
class Father {
public Father(String name) {
System.out.println("接收到name=" + name);
}
//方法
public void test() {
}
}
// 抽象类
abstract class Animal {
abstract void eat();
}
class Outer {
public void method() {
//继承父类的匿名内部类
Father father = new Father("张三"){
@Override
public void test() {
System.out.println("重写父类的方法");
}
};
System.out.println("father对象的运行类型=" + father.getClass()); // 输出 Outer$2
father.test();
}
//继承抽象类的匿名内部类
Animal animal = new Animal() {
@Override
void eat() {
System.out.println("继承抽象类的方法");
}
};
}
public class A{
public static void main(String[] args) {
Outer outer = new Outer();
outer.method();
outer.animal.eat();
}
}1. father编译类型 Father
2. father运行类型 Outer$2
3. 底层会创建匿名内部类,如下
class Outer$2 extends Father{
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
}4. 同时也直接返回了 匿名内部类 Outer$2的对象
5. 注意("张三") 参数列表会传递给 构造器。
class Fu {
int a;
public void test(){};
public Fu(int a) {
this.a = a;
System.out.println(a);
}
public void ok(String str) {
System.out.println("ok(String str) " + str);
test();//动态绑定
}
}
abstract class Animal1 {
abstract void eat1();
}
class Outerclass {
public void Out() {
Fu fu = new Fu(1){
@Override
public void test() {
System.out.println("重写父类Fu()");
}
};
fu.test();
System.out.println("Fu的运行类型" + fu.getClass());
new Fu(2) {
@Override
public void test() {
System.out.println("第二次重写父类Fu()");
}
}.ok("aaa");
}
//继承抽象类的匿名内部类
Animal1 animal1 = new Animal1() {
@Override
void eat1() {
System.out.println("继承抽象类Animal1的方法eat1()");
}
};
}
public class Test3 {
public static void main(String[] args) {
Outerclass outerclass = new Outerclass();
outerclass.Out();
outerclass.animal1.eat1();
}
}
public class Interface01 {
public static void main(String[] args) {
f(new A() {
@Override
public void eat() {
System.out.println("没有创建对象便成功的调用了f方法,不需要实现接口");
}
});
}
public static void f(A a){
a.eat();
}
}
interface A{
public void eat();
}
---------------------------
没有创建对象便成功的调用了f方法,不需要实现接口
局部内部类定义在外部类的局部位置(即方法和代码块中),并且具有类名
局部内部类定义在方法当中,相当于一个局部变量 作用域只在定义它的方法或者代码块中。
在内部类下实例化内部类 使用 外部类名.this.成员 访问与内部类成员变量名相同的外部成员变量
class OutClass {
int a = 10;
public void method(){
int a = 11;
int b = 10;
// 局部内部类:定义在方法体内部
// 不能被public、static等访问限定符修饰
class InnerClass{
public void methodInnerClass(){
System.out.println(a);
//通过类名.this.成员的方式来访问与内部类成员变量名相同的外部类成员变量
System.out.println(OutClass.this.a);
System.out.println(b);
}
}
// 只能在该方法体内部使用,其他位置都不能用
InnerClass innerClass = new InnerClass();
innerClass.methodInnerClass();
}
public static void main(String[] args) {
// OutClass.InnerClass innerClass = null; 编译失败
OutClass outClass = new OutClass();
outClass.method();
}
}