Java内部类

目录

内部类引出

内部类的分类

局部内部类

匿名内部类引出

基于接口的匿名内部类

基于类的匿名内部类

匿名内部类总结

成员内部类

静态内部类


内部类引出

内部类作为oop的最后一个部分,它的重要性不言而喻,在许多底层源码中内部类被大量使用。由它的名字就很容易知道,所谓内部类,就是定义在类的内部的一种类,如以下代码所示:

class Outer{  //外部其他类
}
class Outer01{  //外部类
class Inner{  //内部类
}
}

内部类的分类

内部类可以根据它定义的位置分成两大类

定义在类的局部位置:局部内部类,匿名内部类

定义在类的成员位置:成员内部类,静态内部类

局部内部类

public class Java实验 {  //外部其他类
    public static void main(String[] args) {
        Person person = new Person();  //实例化外部类的对象
        person.get();  //进行输出
    }
}
class Person{  //外部类
    private String name = "小黄";
    public char sex = '男';
    public int age = 19;
    public void get(){
        class GetPerson{  //局部内部类
            public void call(){
                System.out.println("姓名:" + name + " 性别:" + sex + " 年龄:" + age);
            }
        }
        new GetPerson().call();  //在方法内创建内部类的实例并调用内部类的方法
    }
}

输出结果

姓名:小黄 性别:男 年龄:19

由以上代码可知,局部内部类具有以下特点:

1:定义在类的局部位置(方法或代码块)中,具有类名;

2:可以访问外部类的所有属性,包括私有属性;

3:作用域为定义它的方法或代码块;

4:外部其他类不能访问局部内部类。如果要使用,可以在定义它的方法中创建它的实例,然后调用内部类成员。并在外部其他类中创建外部类的实例调用该方法。

局部内部类使用注意:

1:局部内部类的本质依然是类,因此可以有类的所有成员;

2:局部内部类可以被继承(只能在定义它的作用域中被继承);

3:局部内部类不能加访问修饰符,要加也只能加final,加了final的内部类不能被继承;

4:如果外部类的成员和内部类重名时,遵循就近原则。

代码示例:

public class Java实验 {
    public static void main(String[] args) {
        Person person = new Person();
        person.get();
    }
}
class Person{
    private String name = "小黄";
    public char sex = '男';
    public int age = 19;
    public void get(){
        class GetPerson{
            public void call(){
                System.out.println("姓名:" + name + " 性别:" + sex + " 年龄:" + age);
            }
        }
        //局部内部类可以被继承
        class GetSthdent extends GetPerson{
            //局部内部类可以有类的所有成员(本质还是类)
            private String name = "小红";
            public char sex = '女';
            public int age = 20;
            public char grade = 'A';
            //当内部类的成员和外部类的成员重名时,默认遵循就近原则
            //如果还是希望访问外部类的成员,可以用语法:外部类名.this.成员 来访问
            public void call(){
                System.out.println("姓名:" + name + " 性别:" + sex + " 年龄:" + Person.this.age + " 等级:" + grade);
            }
        }
        new GetSthdent().call();
    }
}

 输出结果:

姓名:小红 性别:女 年龄:19 等级:A

注:就近原则:执行操作有重名的成员的语句时,被操作的成员默认是离该语句最近的成员

对语法 外部类名.this.成员 的解释:外部类名.this---相当于指定外部类的对象,如果直接写this.成员,指定的是当前局部内部类的成员,但外部类名.this指定的是所写外部类的成员;

匿名内部类引出

public class Java实验 {
    public static void main(String[] args) {
        Person person = new Person();  //创建人的对象
        person.run();  //使用跑步功能
    }
}
interface A{  //接口
    String name = "小黄";
    void run();
}
class Person implements A{  //Person类实现接口A,实现人的跑步功能
    public void run(){
        System.out.println(name + "跑的很快!");
    }
}

以上代码展示了传统写法中我们实现并使用接口规定的方法时,需要专门写一个类实现接口的方法。但是我们在实际开发中又只使用一次该方法,这么写很不方便;

因此我们可以用匿名内部类来简化代码

基于接口的匿名内部类

public class Java实验 {
    public static void main(String[] args) {
        Person person = new Person();  //创建对象调用get方法
        person.get();
    }
}
interface A{
    String name = "小黄";
    void run();
}
class Person{
    public void get(){
        A person = new A(){  //使用匿名内部类实现接口
            public void run(){  //实现接口的方法
                System.out.println(name + "跑的很快");
            }
        };
        person.run();  //调用匿名内部类的方法
    }
}

运行结果:

小黄跑得很快

由以上代码可知

1:编译类型是接口A,运行类型是匿名内部类;

2:此匿名内部类实现了接口A,可以重写run方法;

3:可以访问外部类的所有成员。

基于类的匿名内部类

public class Java实验 {
    public static void main(String args[]){
        Person person = new Person();
        person.call();    //进行输出
    }
}
class Person{
    private String name = "小黄";
    private int age = 19;
    public char sex = '男';
    public void get(){
        System.out.println("姓名:" + name + " 年龄:" + age + " 性别:" + sex);
    }
    public void call(){
        Person student = new Person(){  //使用匿名内部类
            private char grade = 'A';
            public void get(){   //进行输出(方法重写)
                System.out.println("姓名:" + name + " 性别:" + sex + " 年龄:" + age + " 等级:" + grade);
            }
        };
        student.get();  //调用匿名内部类的方法
    }
}

运行结果:

姓名:小黄 年龄:19 性别:男 等级:A

匿名内部类除了可以基于接口使用,还可以基于类使用:

由以上代码可知:

1:编译类型是Person类,运行类型是匿名内部类;

2:此匿名内部类继承了Person类,可以使用Person类的成员;

3:可以访问外部类的所有成员。

匿名内部类总结

1:语法:类名(接口名) 引用 = new 类名(接口名);

注:如果使用的是接口名创建匿名内部类,则会默认用匿名内部类实现该接口,可以实现接口中的方法

如果使用的是类名创建匿名内部类,则会默认用匿名内部类继承该类,可以使用此类中的成员

匿名内部类的地址会返回给引用,可以用引用调用匿名内部类的方法;

2:匿名内部类的末尾需要打分号;

3:匿名内部类的作用域是定义它的方法或代码块;

4:匿名内部类不是没有名字,而是名字由系统分配,定义者不可见;

注:匿名内部类的名字:外部类名+$n(n为根据定义的匿名内部类的个数分配的编号);

此代码在JVM底层相当于如下语句:

class Person$1 extends Person{
    private char grade = 'A';
    public void call(){
        System.out.println("姓名:" + name + " 年龄:" + age + " 性别:" + sex + " 等级:" + grade);
}
}

成员内部类

public class Java实验 {
    public static void main(String args[]) {  
        Person person = new Person();
        person.user();  //调用user方法
    }
}
class Person{
    private String name = "小黄";
    private int age = 19;
    public char sex = '男';
    public class Student{  //成员内部类
        char grade = 'A';
        public void call(){  //成员内部类的方法
            System.out.println("姓名:" + name + " 年龄:" + age + " 性别:" + sex + " 等级:" + grade);
        }
    }
    public void user(){  //所有方法创建成员内部类的实例,并调用成员内部类的方法
        Student student = new Student();
        student.call();
    }
}

输出结果

姓名:小黄 年龄:19 性别:男 等级:A

由以上代码所示,成员内部类由以下特点:

1:成员内部类定义在外部类的成员位置,没有static修饰;

2:可以直接访问外部类的所有成员,包含私有的;

3:可以添加任意的的访问修饰符;

4:作用域和外部类的其他成员一样,为整个类体;

外部其他类的访问方式 : 

1:在外部其他类中直接创建成员内部类的对象,语法:外部类名.成员内部类名 引用 = new 外部类名.new 成员内部类名

2:在外部类中用一个方法创建成员内部类的对象调用成员内部类,在外部其他类中创建外部类的对象调用此方法。(如以上代码) 。

第一种方式示例:

public class Java实验 {
    public static void main(String args[]) {
        Person.Student student = new Person().new Student();  //直接创建内部类的对象
        student.call();
    }
}
class Person{
    private String name = "小黄";
    private int age = 19;
    public char sex = '男';
    public class Student{  //成员内部类
        char grade = 'A';
        public void call(){  //成员内部类的方法
            System.out.println("姓名:" + name + " 年龄:" + age + " 性别:" + sex + " 等级:" + grade);
        }
    }
}

输出结果同上。

静态内部类

public class Java实验 {
    public static void main(String args[]) {
        Person person = new Person();
        person.f1();
    }
}
class Person{
    static private String name = "小黄";
    static private int age = 19;
    public char sex = '男';
    static class Student{  //静态内部类
        char grade = 'A';
        static void call(){  //静态内部类的方法
            System.out.println("姓名:" + name + " 年龄:" + age);
        }
    }
    public void f1(){
        Student.call();  //使用类名直接调用
    }
}

运行结果:

姓名:小黄 年龄:19

由以上代码所示,静态内部类具有以下特点:

1:静态内部类有static修饰,定义在类的成员位置;

2:可以直接访问外部类的所有静态成员,包含私有的,但不能访问非静态成员;

3:可以添加任何访问修饰符;

4:作用域和其他成员一样,为整个类体;

访问方式:

1:直接在外部其他类创建对象:语法:外部类名.静态内部类名 引用 = new 外部类名.静态内部类名;

2:在外部类中使用方法创建静态内部类的对象调用静态内部类,在外部其他类中创建外部类的对象调用此方法;(如以上代码)

第一种方式示例:

public class Java实验 {
    public static void main(String args[]) {
        Person.Student student = new Person.Student();  //直接创建静态内部类的对象
        student.call();
    }
}
class Person{
    static private String name = "小黄";
    static private int age = 19;
    public char sex = '男';
    static class Student{  //静态内部类
        char grade = 'A';
        static void call(){  //静态内部类的方法
            System.out.println("姓名:" + name + " 年龄:" + age);
        }
    }
}

输出结果同上。 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值