对于外部类的局部内容,正在深刻理解中。每天都在批改更新中。
一、成员外部类
/** * 须要晓得两个前提: * 1.成员外部类是外围类的一个成员,它两关系特地好,开诚布公,抵足而眠,都是最好的亲兄弟 * 所以拜访权限什么的,基本不存在 * * 2.外部类对象依赖于外围类对象存在 * 思考: * a,在成员外部类的成员办法中,有没有外围类对象呢? 有 * * 成员外部类的成员办法必然是成员外部类的对象去调用的【了解】 * 既然都曾经有成员外部类的对象了,【为什么???】所以这里肯定有外围类对象 * * b,在外围类的成员办法中,有没有外部类对象? 没有 * 外部类对象依赖于外围类对象存在,外围类的对象尽管存在,然而外部类的对象就不肯定了 *========================================================================================== * - 【1】成员外部类外部拜访外围类 * 1,能够间接拜访,不管拜访权限 * 2,如果拜访外围类的动态成员,倡议加上外围类类名(这样可读性更好) * 3,外部类的成员办法中隐含了传参EnclosedClazz.this,示意以后外部类的外围类对象 * 能够用这个来解决外围类和外部类的同名成员问题 * 当然 也隐含了一个this,代表以后外部类对象 * * 这个this能够用来解决局部变量和成员变量同名的问题 * * - 【2】外围类拜访成员外部类成员 * (1)在外围类的一般成员办法中 要本人手动创立外部类对象 能够用这个对象任意拜访外部类成员,不管拜访权限 * (2)如果在外围类的静态方法中 拜访外部类成员。必须创立两个对象 外围类对象的根底上创立外部类对象 * * - 【3】外部类拜访成员外部类成员 * 必须要先创立外围类对象 再创立外部类对象 * 留神:外部类拜访外部类 受拜访权限限度 * 1,如果外部类是公有的,外部类无奈创建对象 * 2,即使是可能创建对象,外部类中的公有成员也不能拜访 * * - 【4】成员外部类拜访外部类成员(理解) * > 在成员外部类中拜访外部类成员,和在一般类中拜访其它类成员别无二致 * * - 动态成员间接类名点拜访 * - 一般成员需创立外部类对象 * - 都受拜访权限管制 */public class OutsideClazz { //外部类 public static void main(String[] args) { //创立外部类对象 //这里有没有外围类对象 //EnclosedClazz enclosedClazz = new EnclosedClazz(); // //EnclosedClazz.InnerClazz innerClazz = enclosedClazz.new InnerClazz(); // //上面的格局 是创立成员外部类对象的万能格局 //二合一 EnclosedClazz.InnerClazz innerClazz = new EnclosedClazz().new InnerClazz(); //System.out.println(innerClazz.a); }}class EnclosedClazz{ //外围类 //外围类中成员变量 int a; private int b = 10; static int c = 20; static final int D = 30; //(1)外围类中的成员办法 public void test(){ //拜访外部类成员必须要有外部类对象 //这里有没有? 显然是没有的 所以要本人创建对象 //这里曾经存在了一个外围类对象【为什么???】 ,用this批示 所以间接创立外部类对象即可 InnerClazz innerClazz = new InnerClazz(); System.out.println(innerClazz.a);//不受拜访权限限度 //拜访外部类的动态常量,间接用外部类类名就能够了 System.out.println(InnerClazz.D); //EnclosedClazz.InnerClazz innerClazz2 = new EnclosedClazz().new InnerClazz(); } //(2)外围类的静态方法中 public static void testStatic(){ //外围类的静态方法 这里有没有对象? 这里没有任何对象 包含外围类对象 //所以在这里拜访成员外部类成员 必须创立两个对象 //1创立外围类对象 EnclosedClazz enclosedClazz = new EnclosedClazz(); //2创立外部类对象 InnerClazz innerClazz = enclosedClazz.new InnerClazz(); //3下面能够二合一 //有对象后,拜访就一样了 不受拜访权限管制 InnerClazz innerClazz1 = new EnclosedClazz().new InnerClazz(); //EnclosedClazz.InnerClazz innerClazz2 = new EnclosedClazz().new InnerClazz(); } class InnerClazz{ //成员外部类 //思考:如果外部类中有和外围类同名的动态变量咋办? 错了 成员外部类没有动态变量 //static int c = 200; //思考:如果外部类中有和外围类同名的动态常量咋办? 就用类名辨别 //思考:如果外部类中有和外围类同名的一般变量咋办? 一般类的成员办法中隐含了this传参 代表以后对象 //而成员外部类的成员办法中也隐含了一个参数 代表以后外部类的外围类对象 用EnclosedClazz.this标记它 static final int D = 300; private int a = 10; //依赖办法拜访外围类成员 成员外部类的成员办法必然是成员外部类的对象去调用的【了解】 public void testInner(){ System.out.println(EnclosedClazz.this.a);//拜访外围类的同名一般成员变量 System.out.println(b);//成员外部类是外围类的一个成员,不存在拜访权限 System.out.println(EnclosedClazz.c);//拜访外围类的动态成员,倡议加上外围类类名(这样可读性更好) System.out.println(EnclosedClazz.D);//同上 这里D为外围类中的30 System.out.println(this.D);//也隐含了一个this,代表以后外部类对象 这里D为300 } }}
二、动态外部类
/** * 前提: * 1,只有是外部类,外围类都是亲兄弟,都没有拜访权限限度 * 2,外围类和外部类对象就不会相互影响了 各干各的 * * 需要:不心愿依赖外围类,又不心愿外部类可能拜访,只能用动态外部类 * - 【1】动态外部类外部拜访外围类 * 必须要创立外围类对象 动态成员举荐类名拜访 不受拜访权限管制 * * - 【2】外围类拜访动态外部类成员 * 无论是什么办法,间接创立外部类对象完事 不受拜访权限限度 如果是动态成员举荐应用类名拜访 * * - 【3】外部类拜访动态外部类成员 * 这里动态外部类是一个能够独立的类 * 惟一的区别 就是须要类的申明拜访权限限度 * 语法: * EnclosedClazz.InnerStaticClazz ecisc = new EnclosedClazz.InnerStaticClazz(); * * - 【4】动态外部类拜访外部类成员(理解) * > 在动态外部类中,拜访外部类成员,和在一般类中拜访其余类成员别无二致 * * - 动态成员,类名点间接拜访 * - 一般成员需创建对象拜访 * - 受拜访权限管制 * */public class OutsideClazz { //外部类 public static void main(String[] args) { //创立外部类对象 //能够间接创立 然而它和一般类不同 //须要通知编译器 你这个外部类在哪里 //EnclosedClazz.InnerClazz ic = new EnclosedClazz.InnerClazz(); //System.out.println(ic.privateVar); }}class EnclosedClazz { //外围类 int aEn; private int aEnPrivate = 10; static int b = 10; //成员办法 public void test(){ //这里没有动态外部类对象,须要创立 //不受拜访权限限度 } public static void testStatic(){ //须要创立外围类对象吗? InnerClazz innerClazz = new InnerClazz(); } private static class InnerClazz { //动态外部类 //尽管这个类加了static 然而你不要往动态成员思考 这里static示意这个外部类是独立的 //定义成员变量 int aEn; private int privateVar = 100; private static int b = 10; static int c = 20; static final int D = 30; //定义成员办法 public void test(){ //拜访外围类成员 须要外围类对象 //思考:这里有没有外围类对象? //这里没有外围类对象,须要创立外围类对象 EnclosedClazz ec = new EnclosedClazz(); System.out.println(ec.aEn); //外围类的就用外围类对象办法 System.out.println(ec.aEnPrivate); //思考:这里如果外部类和外围类同名变量 //外围类的就用外围类对象办法,本人的就用this拜访 System.out.println(this.aEn); //用this减少区分度 本人的就用this拜访 System.out.println(InnerClazz.b);//动态成员举荐类名拜访 } public static void testStatic(){} } class InnerStatic{}}
三、部分外部类
public class Demo { //外部类 public static void main(String[] args) { //int a = 10; for (int i = 0; i < 1; i++) { class T{} } if (true){ class T{} } //switch } static { class S{} }}class EnclosedClazz { //外围类 public void test() { //一般的成员办法 //定义部分外部类 class InnerLocalClazz{ int a; private int b = 10; //Inner classes cannot have static declarations //static int c =100; static final int D = 100; //动态常量是不须要类加载 //Inner classes cannot have static declarations //static final Demo DEMO = new Demo();//动态的援用类型常量 只有String不触发类加载 public void test(){} //public static void test2(){} } }}=====================================================================================public class Demo { public static void main(String[] args) { }}class EnclosedClazz { //外围类 int a; private int b = 20; static int c = 10; public static void main(String[] args) { EnclosedClazz enclosedClazz = new EnclosedClazz(); enclosedClazz.test(); } public void test() { //一般成员办法 //能够间接拜访外围类成员,因为一般成员办法隐含this指向以后对象 所以曾经有对象 //可能间接拜访 class InnerLocalClazz { //部分外部类 //部分外部类的成员办法 public void test() { System.out.println(a); //0 System.out.println(b); //20 System.out.println(EnclosedClazz.c); //10 } } //在办法中创建对象 //触发类加载 也只有这一种形式 只能在这里创建对象 InnerLocalClazz innerLocalClazz = new InnerLocalClazz(); //调用部分外部类的办法 innerLocalClazz.test(); //这里输入3个值 } public static void testStatic() { //动态成员办法 class InnerLocalClazz{ //思考:这里可能间接拜访外围类成员吗? //不能,起因是动态的办法没有以后对象 public void test(){ //System.out.println(b); } } }}部分外部类对象和办法局部变量的生命周期比照部分外部类对象要比局部变量活得更久 jvm放的正本啥时候隐没:跟对象同生共死在Java8之前,这个办法的局部变量中的final必须由程序员手动加上去的,然而8当前,Java开发者把这个final暗藏到了代码底层public class Demo { //外部类 public static void main(String[] args) { EnclosedClazz enclosedClazz = new EnclosedClazz(); Father f = enclosedClazz.test(); //这里返回的理论是一个InnerSon对象 //父类援用指向子类对象 多态调用 f.testInner(); //这里曾经没有a了 //然而依然可能打印a的值,阐明jvm偷偷的帮咱们做了一件事: // 把办法的局部变量a 塞到了对象当中 }}class EnclosedClazz { //外围类 public Father test() { //定义部分外部类 让它继承Father int a = 10; //当test调用完结 a就销毁了 无了 class InnerSon extends Father{ @Override public void testInner() { System.out.println("2"); //a = 20; //System.out.println(a); } } //再次用a //创立部分外部类对象 InnerSon is = new InnerSon(); //我间接把这个对象作为返回值返回 return is; //子类能够看成父类 向上转型 主动 //is.test(); //2 }}class Father { public void testInner() { System.out.println("1"); }}=====================================================================================部分外部类的经典应用/** *写一个办法去返回接口或者抽象类的具体子类 * * 用部分外部类返回一个接口实现类 适宜用于想偷懒 不想写接口实现类的适宜 * 适宜于 只应用一次的实现类 或者就想调用一次接口的办法 * 然而对于屡次调用,这种形式就不实用 * */public class Demo { public static void main(String[] args) { //经典写法调用 I i = getIInstance(); i.test(); //外部类的高端写法 调用 I i2 = getIInstance2(); i2.test(); } public static I getIInstance(){ //经典写法 //先用一个类实现这个接口 //而后创立这个类的对象 return new IImpl(); //匿名对象 } //高端的写法,应用部分外部类 public static I getIInstance2(){ //定义部分外部类 class IInner implements I{ @Override public void test() { System.out.println("222222"); } } //创立部分外部类对象 //IInner iInner = return new IInner(); }}interface I{ void test();}class IImpl implements I{ @Override public void test() { System.out.println("1111111"); }}
四、匿名外部类
/** * 匿名外部类:是匿名的(部分)外部类,也就是说匿名外部类实质上是部分外部类 * 匿名对象:没有名字的对象 * 匿名外部类:没有名字的(部分)外部类 * * 匿名外部类的应用优缺点: * 1,当咱们只应用一次某类或者某接口的子类对象时,应用匿名外部类,会略微不便一点 * 2,如果须要屡次拜访子类对象的成员,匿名外部类很麻烦。 * 3,如果拜访匿名子类中的独有办法,必须用匿名对象去拜访 * */public class Demo { public static void main(String[] args) { //老花样:创立接口的实现类 I i = new IA(); i.test(); //新花样:部分外部类创立接口实现类 class InnerLocalClazz implements I{ @Override public void test() { System.out.println("高端的写法,总是这么朴实无华,干燥!"); } } //间接创立部分外部类对象 InnerLocalClazz innerLocalClazz = new InnerLocalClazz(); innerLocalClazz.test(); //新新花样:在部分外部类的根底上,我罗唆连你这个外部类我都不要了,间接创立部分外部类对象,也就是匿名部分类 //语法: 间接创建对象: new 接口或者类(){}; //形式一 I i2 = new I() { @Override public void test() { System.out.println("我是匿名外部类对象中的test办法"); } public void test2(){ } };//new加上前面一块就是对象,能够用父类去接管它。实际上想接管 也只能用父类去接管 i2.test(); //i2.test2(); 因为编译看右边,所以调用不了子类独有办法 //((I) i2).test2(); //因为这个子类是匿名的,也没有方法强转它 //总结,这种形式 打死了 也拜访不了子类的独有办法 //形式二 //以上匿名外部类的对象也能够不接管 new I(){ @Override public void test() { System.out.println("不必父类接管"); }public void test2() { System.out.println("子类独有"); } }.test2(); //以上两种形式,各有什么优缺点 //形式一用接口去接管后,这个对象就有援用,能够重复应用,然而形式一是用父类援用去接管的,这样就用不了子类中独有的办法 //形式二没有去接管,这个对象没有援用,只能用一次,用完后就成为垃圾了。然而形式二 能够调用子类独有办法 //形式一 形式二如果都能用 优先应用形式二 因为形式二省事 //用匿名外部类创立类的子类 //语法:new 类(){}; new A(){ @Override public void test() { System.out.println("我是一般类的匿名外部类子类对象"); } }.test(); System.out.println(new AbstractA() { @Override public int test() { return 10; } }.test());//这一块相当于就是10 所以就能够对他进行 10 的操作 比方赋值 比方计算 比方打印 A a = new A() { }; //它如果可能做本人,那它到底是什么类型呢? 如果它做儿子,还能用父类来接管 隐含的继承 }}interface I{ void test();}class IA implements I{ @Override public void test() { System.out.println("我是IA I接口的实现类"); }}class A{ public void test(){}}abstract class AbstractA{ public abstract int test();}