day_11:内部类、内存图

内部类

  在一个类的内部定义的类称为内部类。内部类允许把一些逻辑相关的类组织在一起,并且控制内部类的可视性。

  分类

    变量:成员变量、静态变量、局部变量

    内部类:成员内部类、静态内部类、接口内部类、局部内部类、匿名内部类

  成员内部类

 

//外部类
public class Outter {
    private String str1 = "outterStr1";
    String str2 = "outerStr2";
    protected String str3 = "outerStr3";
    public String str4 = "outerStr4";

    // 成员内部类
    // 在内部类中如何调用外部类的属性:直接调用
    public class Inner {
        private String str1 = "innerStr1";

        public void print() {
            System.out.println(str1);//当外部类属性和内部类属性名相同时,默认调用内部类的属性
            System.out.println(Outter.this.str1);//当外部类属性和内部类属性名相同时,指定调用外部类的属性
            System.out.println(str2);
            System.out.println(str3);
            System.out.println(str4);
        }
    }

    public void print() {
        // 创建内部类的对象
        Inner in = new Inner();
        // 调用内部类的方法
        in.print();
    }
}
Outter.java
public class test01 {
    public static void main(String[] args) {
        //解决方案一:外部类创建方法,在方法中创建内部类对象,再通过内部类对象调用内部类方法
        Outter out = new Outter();
        out.print();
        //解决方案二:创建外部类的对象再创建内部类的对象
        Inner in = new Outter().new Inner();
        in.print();
    }
    
}
test01.java

  静态内部类

  静态内部类是否可以直接访问到外部类的非静态成员变量?

    不可以,因为静态内部类实例的存在,不需要建立在外部类实例存在的前提下,所以内部类不能直接访问外部类的费静态变量。

//外部类
public class Outter {
    
    public static String str1 = "str1";
    
    //静态内部类
    public static class Inner{
        public void print() {
            /**
             * 静态内部类里为什么只能调用外部类的静态属性?
             * 创建静态内部类时,不用创建外部类对象是,所以外部类的属性不能加载到内存中
             * 但是创建静态内部类对象时,会先加载外部类的字节码文件,这是系统会扫描外部类
             * 字节码里的静态属性,并存入到静态常量池中,静态内部类就能找到静态常量区中的变量了
             */
            System.out.println("内部类的print方法"+str1);
            System.out.println("内部类的print方法"+Outter.str1);
            
        }
    } 

}
Outer.java
public class test01 {

    public static void main(String[] args) {
        //创建静态内部了对象的方式
        Inner in = new Outter.Inner();
        in.print();    
    }
    
}
test01.java

  接口内部类

public interface IOutter {

    // 接口内部类
    // public static final class Inner
    class Inner {
        public void print() {
            System.out.println("内部类里的print方法");
        }
    }
}
IOutter.java
public class test01 {

    public static void main(String[] args) {
        Inner in = new IOutter.Inner();
        in.print();
    }

}
test01.java

  局部内部类

    局部内部类是在一个方法内定义的内部类,其可见范围是当前方法,和局部变量一样,局部内部类不能采用访问控制修饰符(private,protected,public,static)来修饰。

public class Outter {

    public int add(int a,int b) {
        final int i = 10;
        
        //局部内部类:局部内部类不能用修饰符修饰
        class Inner{
            public int add(int a,int b) {
                /**
                 * 调用外部内部类的局部变量为什么必须添加final?(jdk1.8开始不再添加final,默认添加)
                 * 很哟可能内部类方法还在执行时,外部类方法就执行结束了,这样外部类方法里的局部变量就会被立刻回收掉,
                 * 如果回收掉了,这时内部类方法调用此变量时,就找不到了。如果用final修饰会让外部类方法里的局部变量生命周期更长
                 */
                System.out.println(i);
                return a+b;
            }
        }
        Inner in = new Inner();
        int add = in.add(a, b);
        return add;
    }
}
Outter.java
public class test01 {
    public static void main(String[] args) {
        Outter outter = new Outter();
        int add = outter.add(10, 20);
        System.out.println(add);
    }
}
test01.java

  匿名内部类

    没有名字的内部类,如果说该类只需要创建一次对象且该对象只使用一次,则不需要去创建该类,建议采用匿名内部类的方式,减少类的个数。

public interface I1 {
    public void method();
}
I1.java
public abstract class MyClass {

    public abstract void method();
}
MyClass.java
public class Test01 {

    public static void main(String[] args) {
        //匿名内部类
        //创建了没有名字的类,继承了MyClass类,重写了method方法,并创建了该类的对象,指向父类的引用
        MyClass myClass = new MyClass() {
            
            @Override
            public void method() {
                System.out.println("xxxxxx");
            }
        };
        myClass.method();
        
        //创建了没有名字的类,实现了I1接口里的method方法,并创建了该类的对象
        //指向了接口的引用
        I1 i1 = new I1() {
            
            @Override
            public void method() {
                System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
                
            }
        };
        i1.method();
    }
}
Test01.java

  对于每个内部类来说,java编译器都会为其生成独立的类文件。

  接口回调

public interface I1 {

    public void code();
}
I1.java
public class Test01 {
    
    public static void main(String[] args) {
        
        //计算一段代码的运行时长
        
        long startTime = System.currentTimeMillis();//获得到系统当前时间(1970年1月1日0时0分0秒到现在的毫秒数)
        for (int i = 0; i < 1000; i++) {
            System.out.println("夏凡,感冒了~~~~");
        }
        long endTime = System.currentTimeMillis();
        
        System.out.println(endTime - startTime);
        
    }

}
Test01.java
public class Test02 {
    
    public static void main(String[] args) {
        
        //计算一段代码的运行时长 --- 接口回调
        
        long codeTime = getCodeTime(new I1() {
            @Override
            public void code() {
                for (int i = 0; i < 1000; i++) {
                    System.out.println("夏凡,感冒了~~~~");
                }
            }
        });
        
        System.out.println(codeTime);
    }
        
    public static long getCodeTime(I1 i1){
        long startTime = System.currentTimeMillis();
        i1.code();
        long endTime = System.currentTimeMillis();
        
        return endTime - startTime;
    }
    

}
Test02.java

 内存图

 

 

 

 

 

所以需要将a、b值放在一个数组里面,然后将其返回;

      

 

 

 

 

posted @ 2018-10-29 12:24  cmlx  阅读(529)  评论(0)    收藏  举报