美文网首页
Java 内部类

Java 内部类

作者: sunpy | 来源:发表于2018-10-14 17:19 被阅读9次
    秀秀.jpg

    题外话

    在java源码中像ReentrantLock中自定义了一个同步器使用静态内部类实现的。内部类在源码的很多地方出现,打算系统的研究下。

    为什么使用内部类

    内部类就是将一个类的定义放在了另一个类的定义的内部。
    ① java本身是不支持多继承的,但是通过内部类可以变相实现:内部类继承一个类,然后访问外部类的属性和方法,这样就可以间接的实现(而出现这种情况的原因是每个内部类都可以独立的继承自一个接口的实现类,所以不管外部类是否继承了哪个实现类,对于内部类毫无影响)。
    ② 以ReentrantLock重入锁为例,其中ReentrantLock实现了自定义同步器Sync,公平同步器FairSync,非公平同步器NonfairSync,通过使用这三个内部类对ReentrantLock提供实现接口方法的支持。如果是我们编写ReentrantLock肯定继承AQS类,这样就需要重写AQS类的方法,还有对外提供的方法,还有不对外提供的方法,导致代码逻辑和结构就不清晰。
    ③ 如果我们想给多个不同的行为添加自己的逻辑,就需要创建一个类然后实现多个接口,这样很麻烦,我们只能拿到多个接口,却要为其创建一个类来实现,可以使用匿名内部类,对于拿到的接口,直接使用匿名内部类,更加简单便捷的实现了接口。
    譬如为Runnable接口加入线程的业务逻辑打印当前线程名称:

    public static void main(String[] args) {
            Runnable runnable = new Runnable() {
    
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                }
            };
        }
    

    成员内部类

    public class Outer {
    
        private int age = 12;
        
        public class InnerOne {
            private int age = 13;
    
            public int getAge() {
                return age;
            }
        }
        
        private class InnerTwo {
            private String name = "456";
    
            public String getName() {
                return name;
            }
        }
    }
    
    public class OuterTest {
    
        public static void main(String[] args) {
            Outer outer = new Outer(); 
            InnerOne innerOne = outer.new InnerOne();
            System.out.println("InnerOne Age : " + innerOne.getAge());
        }
    }
    

    说明:
    ① 成员内部类本身是依赖于外部类,所以只能通过外部类来访问成员内部类。
    ② 私有的成员内部类对外部类来说是不可见的。
    ③ 成员内部类不允许定义非可变的静态实例。
    ④ 成员内部类不允许定义静态方法。
    ⑤ 成员内部类中出现和外部类相同属性,以内部类为准。(小范围屏蔽大范围)。

    局部内部类

    public class Outer {
    
        public String myPrint(String tip) {
            class Inner {
                private int age = 13;
    
                public int getAge() {
                    return age;
                }
            }
            
            return tip + new Inner().getAge();
        }
    }
    
    局部内部类打印结果.jpg

    说明:
    ① 局部内部类本身依赖于当前的方法,与所在的外部类无关,方法外无法访问局部内部类。
    ② 局部内部类访问所在方法的局部变量,该变量需要是final修饰的不可变变量。

    匿名内部类

    public class Outer {
    
        public MyService doMyService () {
            final String name = "sunpy";
            
            return new MyService() {
    
                @Override
                public void getMyService() {
                    int age = 18;
                    System.out.println(name + age);
                }
            };
        }
    }
    
    interface MyService {
        public void getMyService();
    }
    
    public class OuterTest {
    
        public static void main(String[] args) {
            Outer outer = new Outer(); 
            outer.doMyService().getMyService();
        }
    }
    
    匿名内部类打印结果.jpg

    说明:
    ① 匿名内部类省略了内部类的创建,但是在访问方法的局部变量时,该变量需要是final修饰的不可变变量。
    ② 匿名内部类没有构造器。
    ③ 匿名内部类只能实现一个接口。

    静态内部类

    public class Outer {
    
        private static int age = 18;
        
        public int getAge() {
            return age;
        }
    
        public static void printAge() {
            System.out.println(age);
        }
        
        public static class Inner {
            
            public void myPrint() {
                
                System.out.println(age);
            }
            
            public static void myPrint2() {
                System.out.println(age);
            }
            
            public void myPrint3() {
                printAge();
            }
        }
    }
    
    public class OuterTest {
    
        public static void main(String[] args) {
            Inner inner = new Inner();
            inner.myPrint();
            Inner.myPrint2();
            inner.myPrint3();
        }
    }
    
    静态内部类打印结果.jpg

    说明:
    ① 创建静态内部类的原因:不需要使用外部类的对象。
    ② 静态内部类可以创建静态方法和非静态方法。
    ③ 静态内部类可以访问外部类的静态变量和静态方法,但是不可以访问非静态变量、非静态方法。

    内部类标识

    如果我们使用外部类Outer,里面定义了内部类Inner,那么在编译期jvm就会将内部类编译成Outer$Inner.class

    内部类标识图.jpg

    相关文章

      网友评论

          本文标题:Java 内部类

          本文链接:https://www.haomeiwen.com/subject/niezaftx.html