java常用类之内部类

java内部类

1 内部类概述

1 概念: 在一个类的内部在定义一个完整的类
2 特点:

  • 编译之后可以生成独立的字节码文件。
  • 内部类可以直接访问外部类的私有成员,而不破坏封装

2 成员内部类

1.成员内部类的定义

  • 在类的内部定义,与实例变量, 实例方法同级别的类;
  • 外部类中的一个实例部分,创建内部类对象时,必须依赖外部类对象

2.成员内部类的创建

  • 内部类的创建,首先要先new一个外部类对象,在通过外部类对象再new一个内部类对象,格式如下:

      方法一:
         //1.实例化一个外部类
          Outer outer=new Outer();
          //2.再通过外部类实例化内部类
          Outer.Inner inner=outer.new Inner();*/
    
      方法二:一部到位
          Outer.Inner inner=new Outer().new Inner();
    
  • 内部类也可是多个的,如下面代码中的InnerTwo类。

3.内部类中属性的调用

  • 可以通过内部类来调用外部类的私有属性。
  • 当外部类和内部类的属性名相同时,我们默认调用的时内部类的属性,要想调用外部的属性,可以通过 外部类名.this.外部类属性名,当属性名不同时也可以使用这中方式,这是一个好习惯。
  • 在内部类中无法创建static 变量,如果创建,会报错,但是可以创建 static final 常量。
  • 内部类也会由构造器(构造方法),当我们实例化一个外部类对象时,会执行外部类的构造器。当我们一部到位实例化一个内部类的对象时,首先会执行外部类构造器,再次会执行内部类的构造器。例如案例2

案例1:

package com.ouc.dem01;

public class Outer {//这是一个外部类
    //实例变量
    private String name="张三";
    private int age=20;

    //内部类
    class Inner{//这是一个内部类
        private String address="北京";
        private String phone="10";
        private String name="李四";
/*
        private static String country="中国";//内部类中无法定义静态变量
*/
        //但是可以定义静态常量
        private static final String country="中国";
        public void show(){
            //打印外部类的属性,当内部类属性和外部类属性的名字相同时可是由 外部类名.this 来访问
            System.out.println(Outer.this.name);//访问外部类的名字
            System.out.println(Outer.this.age);//访问外部类的年龄
            //打印内部类的属性。
            System.out.println(address);
            System.out.println(phone);

        }
    }
    //这是第二个内部类
    class InnerTwo{
        private String name="王五";
        public void run(){
            System.out.println("run");
        }
    }
}


//测试类,main()方法
package com.ouc.dem01;

public class TestOuter {
    public static void main(String[] args) {
/*        //1.创建外部类对象
        Outer outer=new Outer();
        //2.创建内部类对象
        Outer.Inner inner=outer.new Inner();*/
        //一部到位
        Outer.Inner inner=new Outer().new Inner();
        Outer.InnerTwo innerTwo=new Outer().new InnerTwo();
    }
}

案例2:

package com.ouc.dem02;

public class Outer {
    //这是外部类的构造器
    public Outer(){
        System.out.println("我是Outer的构造方法");
    }

    //这是内部类的构造器
    class Inner{
        Inner(){
            System.out.println("我是Inner的构造方法");
        }
    }
}

package com.ouc.dem02;

public class TestOuter {
    public static void main(String[] args) {
//        Outer outer=new Outer(); //只创建外部类对象时,只会执行外部类构造器

        //当创建内部类对象时,会先执行外部类构造器,然后执行内部类的构造器
        Outer.Inner inner=new Outer().new Inner();
    }
}

3 静态内部类

1. 静态内部类的定义:

  • static修饰的类,static 关键字表示类的属性和方法,static 修饰的属性和方法 是和类一个放入内存的,在成员内部类的基础之上,给类添加了一个static关键字,这样就变成了一个静态内部类。

2.静态内部类创建:

  • 静态内部类不依赖外部类对象 ,可直接创建或者通过类名访问,可声明静态成员。
  • 使用static关键字修饰后,内部类和外部类的级别相同,不再是和外部的实例变量同一个级别。
  • 静态内部类可以创建静态属性,而成员内部类不行。

3. 静态内部类如何访问外部类的是属性

  • 由于静态内部类和外部类的级别一致,需要访问静态内部类的属性是,我们需要先实例化一个外部类对象,再通对象.属性名来访问

4. 什么要有静态类
既然静态类和外部类的级别相同,那不是和我们平时写的类一样了吗?为啥要再内部定义静态内部类呢。原因就是静态内部类可以为外部类提供一些功能。

5. 关于静态内部类的构造器

  • 当我们实例化一个外部类时,会执行外部类的构造器,当我们实例化静态内部类时,只会执行静态内部类的构造器,不会执行外部类的构造器,例如案例2
  • 这里和成员内部类不一样,成员内部类实例化时,首先会执行外部类的构造器,再执行内部类的构造器,而静态内部类只会执行自己的构造器。

注意: 只有静态内部类才可以用static来修饰,普通的类不能用static来修饰。

案例1

package com.ouc.dem04;

public class Outer {
    private String name="海文宇";
    private int age=18;

    static class Inner{
        private String address="深圳";
        private String phone="111";
        //静态内部类可以是设置静态变量
        private static String country="中国";
        public void show(){
            //如何调用外部类的属性
            //1.创建外部类对象
            Outer outer=new Outer();
            //2.通过对象.方法名来访问.
            System.out.println(outer.name);
            System.out.println(outer.age);

            //调用静态类的内部属性
            System.out.println(address);
            System.out.println(phone);
        }
    }
}
package com.ouc.dem04;

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

案例2

package com.ouc.dem04;

public class Outer {
    //这是外部类的构造器
    public Outer(){
        System.out.println("我是Outer的构造方法");
    }

    static class Inner{
        Inner(){
            System.out.println("我是Inner的构造方法");
        }
    }
}
package com.ouc.dem04;

public class TestInner {
    public static void main(String[] args) {
        //实例化一个Outer对象
        Outer outer=new Outer();
        //实例化一个Inner对象
        Outer.Inner inner=new Outer.Inner();
    }
}

4 局部内部类

1. 局部类的定义

  • 定义再外部类的方法中,作用范围和创建对象的范围仅限于当前方法。

2. 局部内部类的创建

  • 局部内部类在类的外部类的方法中创建
  • 具备外部类创建时不能用修饰符修饰

3. 关于局部内部类的调用

  • 局部内部类可以直接访问外部类的属性
  • 但是局部内部类不能访问外部类的静态属性和静态方法
  • 局部内部类在调用外部类的属性时,可以直接调用,但是建议写上Outer.this.属性,增加代码的可读性。
  • 在局部内部类中,要想调用内部类的方法,首先要在在创建局部内部类的方法中实例化,在通过实例化对象类调用内部类的方法。
  • 在局部内部类中调用方法中的属性(即调用局部变量),在jdk1.7以前时要求属性为常量,所以要加final,但是jdk1.8以后就不用了,系统默认为常量,所以调用后的属性值就不可修改了。
  • 同样的局部类中不能存在static变量,但是可以存在static final 常量。

4.关于局部内部类的构造器

  • 局部内部类的构造器的执行,首先要实例化外部类对象,然后通过外部类对象调用方法,但是由前提时该方法中应该堆内部类进行实例化,如果部进醒实例化,那这样也不花执行内部类的构造器。

案例1

package com.ouc.dem05;

public class Outer{
    private String name="海文宇";
    private int age=18;


    public void show(){
        //定义一个局部变量
        String address="深圳";
            System.out.println("run");
        //局部内部类,定义再方法中
/*
        局部内部类之前不能加任何的访问修饰符
*/
        class Inner{
            //局部内部类的属性
            private String phone="13712431236";
            private String email="32559773q@qq.com";

            public void show2(){
                //访问外部类的属性
                System.out.println(Outer.this.name);
                System.out.println(Outer.this.age);

                //访问内部类的属性
                System.out.println(this.email);
                System.out.println(this.phone);

                /*访问方法中的属性,address
                在jdk1.7中:要求必须时常量;在jdk1.8中,不用,应为会默认的给他加final
                所以,address被默认为常量,就不可修改*/
                System.out.println(address);
            }
        }
        Inner inner=new Inner();
        inner.show2();
    }
}
package com.ouc.dem05;

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

案例2

package com.ouc.dem06;

public class Outer {
    public Outer(){
        System.out.println("我是Outer的构造器");
    }
    public void show(){

        class Inner{
            Inner(){
                System.out.println("我是Inner构造器");
            }
        }
        Inner inner=new Inner();
    }
}

package com.ouc.dem06;

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

5 匿名内部类

1. 匿名内部类的定义

  • 匿名内部类就是没有名字的局部内部类,他的一切特性和局部内部类相同
  • 必须继承一个父类和接口
  • 匿名内部类实际上就是定义类,实现类,创建对象的语法合并,只能创建一个该类的对象
  • 优点:减少代码量;缺点:可读性差;

案例1

package com.ouc.dem07;

//这是一个接口
public interface Usb {
    //定义了一个服务方法
    void server();
}

package com.ouc.dem07;

public class Mouse implements Usb {
    @Override
    public void server() {
        System.out.println("连接电脑成功,鼠标开始工作了");
    }
}

package com.ouc.dem07;

public class TestUsb {
    public static void main(String[] args) {
/*        Usb usb=new Mouse();
        usb.server();*/

/*        //在main方法中 定义一个局部内部类
        class Fan implements Usb{
            @Override
            public void server() {
                System.out.println("连接电脑成功,风扇开始工作了");
            }
        }
        //使用局部类创建对象
        Usb usb=new Fan();
        usb.server();*/

        //使用匿名内部类优化(相当创建了一个局部类)
        Usb usb=new Usb() {
            @Override
            public void server() {
                System.out.println("连接电脑成功,风扇开始工作了");
            }
        };
        usb.server();

    }
}

总结:
所谓内部内就是在一个类的内部定义一个完整的类,下面综合上面做做区分:
1.位置

  • 成员内部类是定义在一个类里面,等级和成员变量的等级相同
  • 静态内部类也是定义在类里面,但是用static修饰的类
  • 局部内部类定义在方法里,和方法内的属性等级相同
  • 匿名内部类也是定义在方法里,但是没有名字。

2.内部类的创建

  • 成员内部类的实例化要先实例化一个外部类,在通过外部类来new一个内部类。
  • 静态内部类的实例化和外部类没有关系,可以直接正常实例化。
  • 局部内部类无法通过外部类来实例化内部类对象,也无法在方法体外实例化这个内部类,只能在方法体里面实例化内部类。
  • 匿名内部和局部内部类一样。

3.关于内部类的构造器

  • 成员内部类实例化后,先执行了外部类的构造器,再执行了内部类的构造器。
  • 静态内部类实例化后只会执行自己的构造器,和外部类无关。
  • 局部内部类实例化只会执行自己的构造器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值