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(); } }
public class test01 { public static void main(String[] args) { //解决方案一:外部类创建方法,在方法中创建内部类对象,再通过内部类对象调用内部类方法 Outter out = new Outter(); out.print(); //解决方案二:创建外部类的对象再创建内部类的对象 Inner in = new Outter().new Inner(); in.print(); } }
静态内部类
静态内部类是否可以直接访问到外部类的非静态成员变量?
不可以,因为静态内部类实例的存在,不需要建立在外部类实例存在的前提下,所以内部类不能直接访问外部类的费静态变量。
//外部类 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); } } }
public class test01 { public static void main(String[] args) { //创建静态内部了对象的方式 Inner in = new Outter.Inner(); in.print(); } }
接口内部类
public interface IOutter { // 接口内部类 // public static final class Inner class Inner { public void print() { System.out.println("内部类里的print方法"); } } }
public class test01 { public static void main(String[] args) { Inner in = new IOutter.Inner(); in.print(); } }
局部内部类
局部内部类是在一个方法内定义的内部类,其可见范围是当前方法,和局部变量一样,局部内部类不能采用访问控制修饰符(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; } }
public class test01 { public static void main(String[] args) { Outter outter = new Outter(); int add = outter.add(10, 20); System.out.println(add); } }
匿名内部类
没有名字的内部类,如果说该类只需要创建一次对象且该对象只使用一次,则不需要去创建该类,建议采用匿名内部类的方式,减少类的个数。
public interface I1 { public void method(); }
public abstract class MyClass { public abstract void method(); }
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(); } }
对于每个内部类来说,java编译器都会为其生成独立的类文件。
接口回调
public interface I1 { public void code(); }
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); } }
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; } }
内存图





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




浙公网安备 33010602011771号