IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java基础——内部类 -> 正文阅读

[Java知识库]Java基础——内部类

基本介绍

一个类的内部又完整的嵌套了另一个类机构。被嵌套的类称为内部类(inner class),嵌套的其他类的类称为外部类(outer class)。是我们类的第五大成员【属性、方法、构造器、代码块、内部类】。内部类最大的特点就是可以直接访问私有属性,并且可以体现类和类之间的包含关系。

如果定义在局部位置(方法/代码块中):

(1)局部内部类(有类名)

(2)匿名内部类(没有类名)

定义在成员位置:

(1)成员内部类(没用static修饰)

(2)静态内部类(使用static修饰)

基本语法

class Outer{????????//外部类

? ? ? ? class inner{????????//内部类

????????}

}

class Other{????????//外部其他类

}

public class Demo01 {
    public static void main(String[] args) {

    }
}
class Outher{       //外部类
    private int a=3;//成员一:属性
    public Outher(int a){
        this.a=a;   //成员二:构造器
    }
    {
        System.out.println("代码块");//成员三:代码块
    }
    public void m1(){
        System.out.println("方法");//成员四:方法
    }
    class inner{    //成员五:内部类
        
    }
}

局部内部类

说明:局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。

  1. 可以直接访问外部类的所有成员,包含私有的。
  2. 不能添加访问修饰符,因为它的地位是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final(但是加了final后不能被继承)。
  3. 作用域:仅仅在定义它的方法或代码块中。
  4. 局部内部类--访问---》外部类的成员(直接访问即可)
  5. 外部类--访问--》局部内部类的成员(创建对象,再访问,但是要在作用域内)
    1. 局部内部类定义在方法中/代码块
    2. 作用域在方法体或代码块中
    3. 本质仍然是一个类
  6. 外部其他类--不能访问--》局部内部类(因为局部内部类是一个局部变量)。
  7. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类.this.成员)去访问。
public class Demo01 {
    public static void main(String[] args) {
        Outher outher = new Outher(5);
        outher.m1();
        System.out.println("outher的hashcode="+outher);
    }
}
class Outher{       //外部类
    private int a;//属性
    public Outher(int a){
        this.a=a;   //构造器
    }
    private void m2(){
        System.out.println("方法m2");
    }
    public void m1(){
        //1.局部内部类时定义在外部类的局部位置,通常在方法
        //3.不能添加访问修饰符,但是可以使用final修饰(不能被继承)
        //4.作用域:仅仅在定义它的方法或代码块中
        final class Inner{    //内部类(本质依旧是一个类)
            public void m3(){
                //2.可以直接访问外部类的所有成员,包括私有的。
                //6.如果外部类和局部内部类成员重名,默认遵循就近原则,若想访问外部类的成员,使用(外部类名.this.成员)访问
                int a=100;
                System.out.println(a+"——>内部类的");
                System.out.println(Outher.this.a+"——>外部类的");//Outher.this本质就是外部类的队象,及哪个对象调用了a
                System.out.println("Outher.this hashcode="+Outher.this);
                m2();
            }
        }
        //5.外部类在方法中,可以直接创建内部类对象,然后调用方法即可。
        Inner inner = new Inner();
        inner.m3();
    }
}

匿名内部类

  1. 本质是类。
  2. 内部类。
  3. 该类没有名字。
  4. 同时还是一个对象。

说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名。

匿名内部类的基本语法

new 类或接口(参数列表){

?类体

};

public class Demo02 {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.method();
    }
}
class Outer{//外部类
    private int a=10;//属性
    public void method(){//方法
        //基于接口的匿名内部类
        //需求:实现IA接口,并创建队象。
        //一般是先用一个类实现接口,然后创建对象。编译类型是接口,运行类型是实现类。
//        IA person=new Person();
//        person.cry();
        //可以使用匿名内部类实现简化开发,只使用一次实现类
        //即编译类型依旧是接口,但此时运行类型变为了匿名内部类。
        //匿名内部类只能使用一次。
        //底层代码如下
        /*
        class Outer$1 implements IA{
            @Override
            public void cry(){
                System.out.println("人在哭泣");
            }
        }
         */
        //jdk 底层在创建匿名内部类Outher$1,立即就创建了Outher$1实例,把地址返给ia。
        IA ia = new IA(){
            @Override
            public void cry(){
                System.out.println("人在哭泣");
            }
        };
        System.out.println("基于接口的匿名内部,类运行类型为:"+ia.getClass());//一般为外部类名+$1
        ia.cry();
        ia.cry();//ia是对象是可以反复使用的。

        //基于类的匿名内部类
        //此时father的编译类型为Father1类,运行类型为匿名内部类。
        //底层创建匿名内部类Outer$2
        /*
        class Outer$2 extends Father1{
            @override
            public void cname(){
                system.out.println("匿名内部类重写cname方法")
            }
        }
         */
        //返回给father匿名内部类Outer$2对象
        //("jack")参数列表会传递给 构造器。
        Father1 father = new Father1("jack"){
            @Override
            public void cname(){
                System.out.println("基于类的匿名内部类,匿名内部类重写cname方法");
            }
        };
        System.out.println("运行类型为:"+father.getClass());//Outer$2
        father.cname();

        //基于抽象类的匿名内部类
        Animal animal = new Animal(){//虽然抽象类不能用new实例化,但此时的new Animal()实际上是创建匿名内部类
            @Override
            public void eat(){
                System.out.println("狗吃肉");
            }
        };
        System.out.println("基于类的匿名内部类,运行类型为:"+animal.getClass());//Outer$3
        animal.eat();
    }
}
interface IA{//接口
    public void cry();
}
//class Person implements IA{//接口实现类
//    @Override
//    public void cry(){
//        System.out.println("人在哭泣");
//    }
//}

class Father1{
    public Father1(String name){
        System.out.println("父亲的名字:"+name);
    }
    public void cname(){
    }
}

abstract class Animal{
    abstract void eat();
}

?

  1. 匿名内部类的语法比较奇特,因为匿名内部类即是一个类的定义,同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,对上面代码可以看出这一特点,因此也可以调用匿名内部类方法。
  2. 可以直接访问外部类的所有成员,包含私有的。
  3. 不能添加访问修饰符,因为它的地位就是一个局部变量。
  4. 作用域:仅仅在定义它的方法或代码块中。
  5. 匿名内部类——访问——外部类成员(直接访问即可)。
  6. 外部其他类——不能访问——匿名内部类(因为匿名内部类地位是一个局部变量)。
  7. 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)访问。
public class Demo03 {
    public static void main(String[] args) {
        Outer01 outer01 = new Outer01();
        outer01.f1();
    }
}
class Outer01{
    private int a=3;
    public void f1(){
        //不能添加访问修饰符,但是可以使用final修饰(不能被继承)
        //作用域:仅仅在定义它的方法或代码块中
        final Son son=new Son(){
            int a=5;
            //可以直接访问外部类的所有成员,包括私有的
            //如果外部类和局部内部类成员重名,默认遵循就近原则,若想访问外部类的成员,使用(外部类名.this.成员)访问
            @Override
            public void hi() {
                System.out.println("动态绑定的匿名内部类重写hi()方法 "+a);
            }
            @Override
            public void run(String name) {
                System.out.println("动态绑定的匿名内部类重写hi()方法 "+name+" "+Outer01.this.a);
            }
        };
        son.hi();//动态绑定机制,编译类型为Son 运行类型为匿名内部类Outer01$1
        son.run("jack");
        //也可以直接调用,匿名内部类本身也是返回对象
        new Son(){
            int a=66;
            @Override
            public void hi() {
                System.out.println("匿名内部类重写hi()方法 ");
            }

            @Override
            public void run(String name) {
                System.out.println("匿名内部类重写hi()方法 "+name);
            }
        }.run("jack");

    }
}
class Son{
    public void hi(){
        System.out.println("Son hi()");
    }
    public void run(String name){
        System.out.println(name+"在跑步");
    }
}
当做实参直接传递,简洁高效。
public class Demo04 {
    public static void main(String[] args) {
        //当作实参传递,简洁高效,但是只能使用一次匿名内部类。
        f1(new IL() {
            @Override
            public void say() {
                System.out.println("此时的匿名内部类就是被当作实参");
            }
        });

        //传统方法 这种方法可以多次调用,但是比较繁琐。
        LI li = new LI();
        f1(li);
    }
    public static void f1(IL il){
        il.say();
    }
}
interface IL{
    public void say();
}
class LI implements IL{
    @Override
    public void say(){
        System.out.println("传统方法");
    }
}

成员内部类

说明:成员内部类是定义在外部类的成员位置,并且没有static修饰。

public class Demo05 {
    public static void main(String[] args) {
        Outer02 outer02 = new Outer02();
        outer02.h1();//调用成员内部类,可以先在方法中实例化内部类,然后调用方法。
        outer02.new Inner02().say();//也可直接调用匿名对象的方法。
    }
}
class Outer02{
    private int a=666;
    class Inner02{
        public void say(){
            System.out.println("a="+a);
        }
    }
    public void h1(){
        Inner02 inner02 = new Inner02();
        inner02.say();
    }
}

  1. ?可以直接访问外部类的成员位置,包含私有的。
  2. 可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。
  3. 作用域和外部类的其他成员一样,为整个类体比如前面案例,在外部类的成员方法中创建成员内部类对象,再调用方法。
  4. 成员内部类——访问——外部类成员(直接访问)。
  5. 外部类——访问——成员内部类(要先创建对象,再访问)因为内部类在外部类里,可以访问成员内部类私有属性。
  6. 外部其他类——访问——成员内部类(如下代码)
  7. 如果外部类和成员内部类的成员重名时,成员内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)访问。
public class Demo05 {
    public static void main(String[] args) {
        Outer02 outer02 = new Outer02();
        outer02.h1();//调用成员内部类,可以先在方法中实例化内部类,然后调用方法。
        outer02.new Inner02().say();//也可直接调用匿名对象的方法。
        //第一种方法:
        Outer02.Inner02 inner02 = outer02.new Inner02();
        inner02.say();
        //第二种方法:
        Outer02.Inner02 inner = outer02.getInner02();
        inner.say();
    }
}
class Outer02{
    private int a=666;
    class Inner02{
        int a=888;
        public void say(){
            System.out.println("内部类a="+a+" 外部类a="+Outer02.this.a);
        }
    }
    public void h1(){
        Inner02 inner02 = new Inner02();
        inner02.say();
    }
    public Inner02 getInner02(){
        return new Inner02();
    }
}

静态内部类

说明:静态内部类是定义在外部类的成员位置,并且有static修饰。

  1. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员。
  2. 可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。
  3. 作用域:同其他成员,为整个类体。
  4. 静态内部类——访问——外部类(直接访问静态成员)。
  5. 外部类——访问——静态内部类(先创建对象,在访问)。
  6. 外部其他类——访问——静态内部类(如下代码块)
  7. 如果外部类和静态内部类的成员重名时,静态内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)访问。
public class Demo06 {
    public static void main(String[] args) {
        Outer03 outer03 = new Outer03();
        outer03.h1();

        //方式一:
        //因为是静态内部类,可以通过类名直接访问(前提要满足访问权限)
        Outer03.Inner03 inner03 = new Outer03.Inner03();
        inner03.say();
        //方式二:
        //编写一个方法,可以返回静态的对象实例
        Outer03.Inner03 inner = outer03.getInner();
        inner.say();
    }
}
class Outer03{
    private int a=333;
    private static String name="jack";
    private static int m=222;
    static class Inner03{
        public void say(){
            int m=666;
            //System.out.println(a);   //因为是静态内部类,static修饰,所以调用外部类成员只能调用静态成员,不能直接访问非静态成员。
            System.out.println(name);
            System.out.println("内部类m="+m);
            System.out.println("外部类m="+Outer03.m);
        }
    }
    public static void h1(){
        Inner03 inner03 = new Inner03();
        inner03.say();
    }
    public static Inner03 getInner(){
        return new Inner03();
    }
}

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-22 20:26:08  更:2022-02-22 20:28:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:54:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码