基础知识

  • 内部类
  1. 关于内部类的说法, 错误的是
    a. 内部类不能有自己的成员方法和成员变量
    b. 内部类可用abstract 修饰定义为抽象类,也可以用private 或protected 定义
    c. 内部类可作为其他类的成员,而且可访问它所在类的成员
    d. 除static 内部类外,不能在类内声明static 成员

/*
* 内部类分为四种情况:
* 1:成员内部类
* 2:静态内部类
* 3:匿名内部类
* 4:局部内部类(不常用)
* */

1.成员内部类(普通类)

class OutClass {
    private int num = 3;
    class Inner {
        int num = 4;
         void show() {
            int num = 5;
            System.out.println("num:" + num); // num:5
            System.out.println("num:" + this.num); // num:4
            // 内部类直接访问外部类中成员
            System.out.println("num:" + OutClass.this.num);// num:3
        }
    }
}

public class InnerClassDemo01 {
    public static void main(String[] args) {
        // 创建和使用内部类的语法, 如果inner的 private则不能在外部访问
        OutClass.Inner inner = new OutClass().new Inner();
        inner.show();
    }
}

2.静态内部类

class OutClass02 {
    private static int num = 3;
    // 内部类如果有static方法,则本身必须声明为static方式
    static class Inner {
        int num=4;
        void show() {
            System.out.println("show() num:" + num);
        }
        static void show2() {
            System.out.println("show2() num:" + OutClass02.num);
        }
    }
}

public class InnerClassDemo02 {
    public static void main(String[] args) {
        // 内部类是static的创建方式
        OutClass02.Inner inner=new OutClass02.Inner();
        inner.show();
        // 内部类与function都是static的情况
        OutClass02.Inner.show2();
    }
}

静态属性可以直接使用.的方式来调用

3.匿名内部类
最常使用的一种

/*
 * 匿名内部类
 * */
public class InnerClassDemo03 {

    public static void main(String[] args) {
//String[] names = new File("C:/test").list();拿到当前文件夹所有的文件名称
//目的:像过滤指定文件
//String[] names = new File("C:/test").list(new FilenameFilter())文件名的过滤器
//FilenameFilter接口中只有accept方法
        String[] names = new File("C:/test").list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
//              System.out.println("dir:" + dir);
//              System.out.println("name:" + name);
                return name.endsWith(".jar");
            }
        });
        for(String temp:names){
            System.out.println(temp);
        }
    }
}

4.局部内部类(在某个方法内定义的内部类) 只有该方法被调用的时候,该内部类才会被使用

class OuterClass03 {
    int num = 3;
    public Object method() {
        // 内部类在局部位置上,只能访问被final修饰的局部变量
        final int num = 9;
        class Inner {
            public void show() {
                // num 必须设置为final类型
                System.out.println("show...." + num);
                System.out.println("show...." + OuterClass03.this.num);
            }
        }
        // 如果 num 不加 final类型,则意味着返回的对象调用show的时候 show里面的x已经释放了
        Inner inner = new Inner();
        inner.show();
        return inner;
    }
}

public class InnerClassDemo04 {
    public static void main(String[] args) {
        OuterClass03 out = new OuterClass03();
        Object method = out.method();
    }
}

内部类可以用abstract 类型或者protected等访问修饰符来修饰
内部类可作为其他类的成员,而且可访问它所在类的成员
除static 内部类外,不能在类内声明static 成员(普通类不可以声明static 成员)
内部类中,静态方法只能定义在静态内部类中

  • 内部类使用场景

成员内部类使用

/*
 * 成员内部类的使用
 * */
public class InnerUserTest01 {

    public static void main(String[] args) {
        List<String> list=new ArrayList<String>();
        List<Object> list2=new LinkedList<Object>();
        list.iterator();
        list2.iterator();
    }
}

所有的集合类元素都实现了iterator方法

java 定义一个内部类报错 java内部类说法错误的是_内部类

静态内部类

java 定义一个内部类报错 java内部类说法错误的是_System_02

局部内部类

有时候两个接口中所显示的方法名相同,当一个类相同时实现这两个接口时会出现矛盾,并只可以实现一个重名的方法

java 定义一个内部类报错 java内部类说法错误的是_System_03

成员内部类可以很好的解决这个问题
但是如果外部类的一个变量只想让它在不同的方法内部使用,把变量申明成为局部变量
同理,如果实现的method方法指在内部类使用,则只需要在内部方法中创建内部类 –局部内部类
局部内部类中要使用外面的局部变量,则变量必须采用final关键字
解释:如果外面的局部变量不为final 类型,很可能该方法返回内部类对象的时候,该方法已退出,不为final 类型的成员变量已经被销毁 出栈 ,但是用到该内部对象用到了这个变量,所以返回的内部类对象会报错

/*
 * 列举局部内部类的使用场景
 * */
public class InnerUserTest02 {

    public Object demo01() {

        final int num = 1;
        // 局部内部类中要使用外面的局部变量,则变量必须采用final关键字
        class Inner1 implements Interface01 {

            @Override
            public int method() {
                return num + 1;
            }

        }
        return new Inner1();
    }

    public int demo02() {

        final int num = 1;

        class Inner1 implements Interface02 {

            @Override
            public int method() {
                return num * 1;
            }

        }
        int result = new Inner1().method();
        return result;
    }

    public static void main(String[] args) {
        InnerUserTest02 test = new InnerUserTest02();
        System.out.println(test.demo01());
        System.out.println(test.demo02());
    }
  • 内部类优化单例模式

基本单例模式

// 单例饿汉模式: 调用其它方法时,对象也会被创建
public class SingletonDemo01 {

    private static SingletonDemo01 demo;
    private SingletonDemo01() {
    }
    static {
        System.out.println("----static---");
        demo = new SingletonDemo01();
    }
    public static SingletonDemo01 getInstance() {
        return demo;
    }
    //调用其他方法时对象也会被创建
    public static void otherMethod(){
        System.out.println("--------otherMethod---------");
    }
    public static void main(String[] args) {
        SingletonDemo01.otherMethod();
    }

}

懒汉模式单例 每次判断,性能方面是不很好

public class SingletonDemo02 {

    private SingletonDemo02(){}

    private static SingletonDemo02 demo;

    public static SingletonDemo02 getInstance() {
        if (demo == null) { // 每次要进行判断代码不优雅
            synchronized (SingletonDemo02.class) {
                if (demo == null) {
                    demo = new SingletonDemo02();
                }
            }
        }
        return demo;
    }

}

静态内部类实现单例 -核心

public class SingletonDemo03 {

    private SingletonDemo03() {
        System.out.println("SingletonDemo03 is create");
    }

    // 静态内部类,用来实现真正单例
    private static class SingletonHolder {
        private static SingletonDemo03 instance = new SingletonDemo03();
    }
    // 通过此方法获取实例
    public static SingletonDemo03 getInstance(){
        return SingletonHolder.instance;
    }

    public static void otherMethod(){
        System.out.println("-----调用其他方法并不会产生对象------");
    }

    public static void main(String[] args) {
//      SingletonDemo03.otherMethod();
        System.out.println(SingletonDemo03.getInstance());
        System.out.println(SingletonDemo03.getInstance());
    }
}