Java知识梳理03|内部类详解

一.内部类的定义

  • 可以将一个类的定义放在另一个类的定义内部,这就是内部类。

二.内部类的种类

  • 在 Java 中内部类主要分为成员内部类、局部内部类、匿名内部类、静态内部类。

1.成员内部类

  • 成员内部类定义格式。
class A{
    class B{

    }
}
  • 成员内部类无条件访问外部类的属性和方法。
public class Outer {
    private String name = "Outer";
    public void run(){
        System.out.println("Outer run");
    }

    class Inner{
        public void say(){
            System.out.println(name);
            run();
        }
    }

}
  • 外部类想要访问内部类属性或方法时,必须要创建一个内部类对象,然后通过该对象访问内部类的属性或方法。

  • Inner类定义在Outer类的内部,相当于Outer类的成员变量的位置,Inner类可以使用任意访问修饰符。

  • 成员内部类中不能定义static成员,但是可以存在static域,前提是需要使用final关键字进行修饰。

public class Outer {
    private static String oName = "name = Outer";
    public void run(){
        System.out.println("Outer run");
    }

    public static void main(String[] args) {
        Outer outer=new Outer();
        Outer.Inner inner=outer.new Inner();
        System.out.println(inner.iName);
        inner.say();
    }

    class Inner{
        private String iName="name = Inner";
        public static final int age=18;
        public void say(){
            System.out.println(oName);
            System.out.println("age = "+age);
            run();
        }
    }
}
//输出结果:
name = Inner
name = Outer
Outer run
  • 如果成员内部类的属性或者方法与外部类的同名,将导致外部类的这些属性与方法在内部类被隐藏,可按照该格式调用,外部类.this.属性/方法。
public class Outer {
    private static String name = "name = Outer";
    public void run(){
        System.out.println("Outer run");
    }

    public static void main(String[] args) {
        Outer outer=new Outer();
        Outer.Inner inner=outer.new Inner();
        inner.show();
    }

    class Inner{
        private String name="name = Inner";
        public void run(){
            System.out.println("Inner run");
        }
        public void show(){
            System.out.println(new Inner().name);
            System.out.println(name);
            run();
            System.out.println(new Outer().name);
            System.out.println(Outer.this.name);
            Outer.this.run();
        }
    }

}
//输出结果:
name = Inner
name = Inner
Inner run
name = Outer
name = Outer
Outer run

2.局部内部类

  • 局部内部类定义格式
class A{
    public void show(){
        class B{
            
        }
    }
}
  • 局部内部类无条件访问外部类的属性和方法。
public class Person {

    private String name="张三";
    public void introduce(){
        System.out.println("他是"+name);
    }

    public void show(){
        class Hobby{
            private String hobby="跳舞";
            public void say(){
                introduce();
                System.out.println(name+"爱"+hobby);
            }
        }
    }
}
  • 局部内部类嵌套在方法和作用域内的,只是它的作用域发生了改变,它只能在该方法和属性中被使用,出了该方法和属性就会失效。
  • 局部内部类中不能定义static成员,但是可以存在static域,前提是需要使用final关键字进行修饰。
public class Person {

    private String name="张三";
    public void introduce(){
        System.out.println("他是"+name);
    }

    public void show(){
        class Hobby{
            public static final String intr="介绍:";
            private String hobby="跳舞";
            public void say(){
                System.out.println(intr);
                introduce();
                System.out.println(name+"爱"+hobby);
            }
        }
        Hobby hobby=new Hobby();
        hobby.say();
    }

    public static void main(String[] args) {
        Person person=new Person();
        person.show();
//      Hobby hobby=new Hobby(); 编译错误
//      Person.Hobby hobby=new Person.new Hobby(); 编译错误
    }
}
//输出结果:
介绍:
他是张三
张三爱跳舞
  • 如果局部内部类的属性或者方法与外部类的同名,将导致外部类的这些属性与方法在内部类被隐藏,可按照该格式调用,外部类.this.属性/方法。
public class Person {
    private String name="Person";
    public void say(){
        System.out.println(name);
    }
    public void show(){
        class Hobby{
            private String name="Hobby";
            public void say(){
                System.out.println(name);
            }
        }
        Hobby hobby=new Hobby();
        System.out.println(hobby.name);
        hobby.say();
        System.out.println(Person.this.name);
        Person.this.say();
    }
    public static void main(String[] args) {
        Person person=new Person();
        person.show();
    }
}
//输出结果:
Hobby
Hobby
Person
Person

3.匿名内部类

  • 匿名内部类也就是没有名字的内部类。正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写。但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口。
//不使用匿名内部类来实现抽象方法
abstract class Person {
    public abstract void say();
}

class Student extends Person {
    public void say() {
        System.out.println("say");
    }
}

public class Test {
    public static void main(String[] args) {
        Person p = new Student();
        p.say();
    }
}
//输出结果:
say
  • 使用匿名内部类实现抽象方法和接口。
//抽象方法
abstract class Animal {
    public abstract void shout();
}

public class Test{
    public static void main(String[] args) {
        Animal animal=new Animal(){
            public void shout() {
                System.out.println("shout");
            }
        };
        animal.shout();
    }
}
//输出结果:
shout
    
//接口
interface Animal {
    void shout();
}

public class Test{
    public static void main(String[] args) {
        //可用此代码替代下面代码 Animal animal= () -> System.out.println("shout");
        Animal animal=new Animal(){
            public void shout() {
                System.out.println("shout");
            }
        };
        animal.shout();
    }
}
//输出结果:
shout
  • 匿名内部类最常用的情况就是在多线程的实现上,因为要实现多线程必须继承 Thread 类或是继承 Runnable 接口。
//Thread类的匿名内部类实现
public class Test {
    public static void main(String[] args) {
        Thread t = new Thread() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        t.start();
    }
}
//输出结果
1 2 3 4 5
    
//Runnable接口的匿名内部类实现
public class Test {
    public static void main(String[] args) {
        Runnable r = new Runnable() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        Thread t = new Thread(r);
        t.start();
    }
}
//输出结果
1 2 3 4 5

4.静态内部类

  • 静态内部类定义格式
class U {
    static class I {
        
    }
}
  • static 不仅可以修饰成员变量、方法、代码块,它还可以修饰内部类,使用 static 修饰的内部类我们称之为静态内部类。

  • 静态内部类只能访问外围类的静态成员变量和方法,不能访问外围类的非静态成员变量和方法。

public class OutClass {
    private String name="张三";
    private static int age=18;

    public static void staticMethod(){
        System.out.println("outer staticMethod");
    }

    public void method(){
        System.out.println("outer method");
    }

    static class InClass{
        private static String hobby="跳舞";
        public static void dance(){
            System.out.println(new OutClass().name+"爱"+hobby);
        }

        public void show(){
            //System.out.println(name); 错误
            System.out.println("姓名:"+new OutClass().name);
            System.out.println("年龄:"+age);
            staticMethod();
            new OutClass().method();
            //method(); 错误
        }
    }

    public static void main(String[] args) {
        //System.out.println(InCLass.name2); 错误
        InClass inClass=new InClass();
        inClass.show();
        InClass.dance();
    }
}
//输出结果:
姓名:张三
年龄:18
outer staticMethod
outer method
张三爱跳舞
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值