精华内容
下载资源
问答
  • Java内部匿名内部类的用法

    万次阅读 多人点赞 2016-07-21 15:46:41
    Java内部匿名内部类的用法 【尊重原创,转载请注明出处】http://blog.csdn.net/guyuealian/article/details/51981163一、内部: (1)内部的同名方法 内部类可以调用外部的方法,如果内部有同名方法...

    Java内部类和匿名内部类的用法

        【尊重 原创,转载请注明出处 】http://blog.csdn.net/guyuealian/article/details/51981163
    一、内部类: 
          (1)内部类的同名方法
            内部类可以调用外部类的方法,如果内部类有同名方法必须使用"OuterClass.this.MethodName()"格式调用(其中OuterClass与MethodName换成实际外部类名及其方法;this为关键字,表示对外部类的引用);若内部类无同名方法可以直接调用外部类的方法。
            但外围类无法直接调用内部类的private方法,外部类同样无法直接调用其它类的private方法。注意:内部类直接使用外部类的方法与该方法的权限与是否static无关,它取决于内部类是否有同名方法。
    package innerclass;
    public class OuterClass {
    	private void outerMethod() {
    		System.out.println("It's Method of OuterClass");
    	}
    	public static void main(String[] args) {
    		OuterClass t = new OuterClass();
    		OuterClass.Innerclass in = t.new Innerclass();
    		in.innerMethod();
    	}
    
    	class Innerclass {
    		public void innerMethod() {
    		   OuterClass.this.outerMethod();// 内部类成员方法与外部类成员方法同名时,使用this调用外部类的方法
    		   outerMethod();// 内部类没有同名方法时执行外部类的方法
    		}
    		private void outerMethod() {
    			System.out.println("It's Method of Innerclass");
    		}
    	}
    }
         输出结果为:
    It's Method of OuterClass
    It's Method of Innerclass
        (2)内部类访问外部类的变量必须声明为final
          方法中的局部变量,方法结束后这个变量就要释放掉,final保证这个变量始终指向一个对象。
       首先,内部类和外部类其实是处于同一个级别,内部类不会因为定义在方法中就会随着方法的执行完毕而跟随者被销毁。问题就来了,如果外部类的方法中的变量不定义final,那么当外部类方法执行完毕的时候,这个局部变量肯定也就被GC了,然而内部类的某个方法还没有执行完,这个时候他所引用的外部变量已经找不到了。如果定义为final,java会将这个变量复制一份作为成员变量内置于内部类中,这样的话,由于final所修饰的值始终无法改变,所以这个变量所指向的内存区域就不会变。
         注意,若使用JDK1.8,方法中内部类的方法是可以直接访问外部类的方法的局部变量,并且不需要声明为final类型。
    public class OuterClass {
    	int num1 = 0;// 成员变量
    
    	private void outerMethod() {
    		int num2 = 0;// 方法内的局部变量
    		class Innerclass_1 {
    			public void innerMethod() {
    				System.out.println(num1);// 方法中内部类的方法,可以正常访问外部类的成员变量
    				System.out.println(num2);// JDK1.8以前,方法中内部类的方法,不能直接访问外部类的方法的局部变量,必须声明为final
    			}
    		}
    	}
    }
          如果使用JDK1.8以前的版本,Eclipse会出现如下错误提示:

        (3)内部类的实例化
         内部类实例化不同于普通类,普通类可以在任意需要的时候实例化,而内部类必须在外层类实例化以后方可实例化,并与外部类建立关系
         因此在外部类中的非static方法中,是可以实例化内部类对象
    	private void outerMethod() {
    		System.out.println("It's Method of OuterClass");
    		Innerclass in = new Innerclass();//在外部类的outerMethod方法中实例化内部类是可以啊
    	}
          但在static方法中,就要注意啦!!!! 不能在static方法中直接new内部类,否则出现错误:
         No enclosing instance of type OuterClass is accessible. Must qualify the allocation with an enclosing instance of type OuterClass (e.g. x.new A() where x is an instance of OuterClass).
         这是因为静态方法是在类实例化之前就可以使用的,通过类名调用,这时动态内部类都还没实例化呢,怎么用,总不能调用一个不存在的东西吧。
         如果想在Static方法中new内部类,可以把内部类声明为Static
    public class OuterClass {
    	private void outerMethod() {
    		System.out.println("It's Method of OuterClass");
    	}
    
    	public static void main(String[] args) {
    		Innerclass in = new Innerclass();
    		in.innerMethod();
    	}
    
    	static class Innerclass {//把内部类声明为static
    		public void innerMethod() {
    			System.out.println("It's Method of innerMethod");
    
    		}
    	}
    
    }
         当然,一般不使用static的方式,而是推荐这种方法:x.new A() ,其中 x是外部类OuterClass的实例,A是内部类Innerclass
    package innerclass;
    public class OuterClass {
    	private void outerMethod() {
    		System.out.println("It's Method of OuterClass");
    	}
    	public static void main(String[] args) {
    		OuterClass.Innerclass in = new OuterClass().new Innerclass();//使用x.new A()的方式
    		in.innerMethod();
    	}
    	class Innerclass {
    		public void innerMethod() {
    			System.out.println("It's Method of innerMethod");
    		}
    	}
    }
          x.new A() ,其中 x是外部类OuterClass的实例,A是类部类Innerclass,当然可以拆分如下,这样就显然很明白啦:
    	public static void main(String[] args) {
    		OuterClass out = new OuterClass();//外部实例
    		OuterClass.Innerclass in = out.new Innerclass();//外部实例.new 外部类
    		in.innerMethod();
    	}

        (4)什么情况下使用内部类
         典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外层类的对象。所以你可以认为内部类提供了某种进
    入其外层类的窗口。
        使用内部类最吸引人的原因是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外层类是否已经继承了某个(接口的)实
    现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角
    度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。
       (5)在静态方法中实例化内部类例子:(内部类放在静态方法中)
    package javatest2;
    public class JavaTest2 {
    	public static void main(String[] args) {
    		class Boy implements Person {
    			public void say() {// 匿名内部类自定义的方法say
    				System.out.println("say方法调用");
    			}
    			@Override
    			public void speak() {// 实现接口的的方法speak
    				System.out.println("speak方法调用");
    			}
    		}
    		Person per = new Boy();
    		per.speak();// 可调用
    		per.say();// 不能调用
    	}
    }
    interface Person {
    	public void speak();
    }
           per.speak()可调用,而per.say()不能调用,这时因为per是Person对象,要想调用子类的方法,可以强制向下转型为:((Boy) per).say();或者直接改为Boy per = new Boy();。 从中可发现,要想调用内部类的自定义的方法,必须通过内部类的对象来调用。那么,匿名内部类连名字都没有,怎么调用内部类自定义的方法?
    (二)匿名内部类
          匿名内部类也就是没有名字的内部类正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写,但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口,但最多只能继承一个父类,或实现一个接口。
    关于匿名内部类还有如下两条规则:
        1)匿名内部类不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建内部类的对象。因此不允许将匿名内部类定义成抽象类。
        2)匿名内部类不等定义构造器(构造方法),因为匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义实例初始化块,
        怎样判断一个匿名类的存在啊?看不见名字,感觉只是父类new出一个对象而已,没有匿名类的名字。
    先看段伪代码
    abstract class Father(){
    ....
    }
    public class Test{
       Father f1 = new Father(){ .... }  //这里就是有个匿名内部类
    }
       一般来说,new 一个对象时小括号后应该是分号,也就是new出对象该语句就结束了。但是出现匿名内部类就不一样,小括号后跟的是大括号,大括号中是该new 出对象的具体的实现方法。因为我们知道,一个抽象类是不能直接new 的,必须先有实现类了我们才能new出它的实现类。上面的伪代码就是表示new 的是Father的实现类,这个实现类是个匿名内部类。
        其实拆分上面的匿名内部类可为:
    class SonOne extends Father{
      ...       //这里的代码和上面匿名内部类,大括号中的代码是一样的
    }
    public class Test{
       Father f1 = new SonOne() ;
    }
    
         先看一个例子,体会一下匿名内部类的用法:

        运行结果:eat something
        可以看到,我们直接将抽象类Person中的方法在大括号中实现了,这样便可以省略一个类的书写。并且,匿名内部类还能用于接口上
    public class JavaTest2 {
    	public static void main(String[] args) {
    		Person per = new Person() {
    			public void say() {// 匿名内部类自定义的方法say
    				System.out.println("say方法调用");
    			}
    			@Override
    			public void speak() {// 实现接口的的方法speak
    				System.out.println("speak方法调用");
    			}
    		};
    		per.speak();// 可调用
    		per.say();// 出错,不能调用
    	}
    }
    
    interface Person {
    	public void speak();
    }
            这里per.speak()是可以正常调用的,但per.say()不能调用,为什么呢?注意Person per = new Person()创建的是Person的对象,而非匿名内部类的对象。其实匿名内部类连名字都没有,你咋实例对象去调用它的方法呢?但继承父类的方法和实现的方法是可以正常调用的,本例子中,匿名内部类实现了接口Person的speak方法,因此可以借助Person的对象去调用。
            若你确实想调用匿名内部类的自定义的方法say(),当然也有方法:
          (1)类似于speak方法的使用,先在Person接口中声明say()方法,再在匿名内部类中覆写此方法。
          (2)其实匿名内部类中隐含一个匿名对象,通过该方法可以直接调用say()和speak()方法;代码修改如下:
    public class JavaTest2 {
    	public static void main(String[] args) {
    		new Person() {
    			public void say() {// 匿名内部类自定义的方法say
    				System.out.println("say方法调用");
    			}
    
    			@Override
    			public void speak() {// 实现接口的的方法speak
    				System.out.println("speak方法调用");
    			}
    		}.say();// 直接调用匿名内部类的方法
    	}
    }
    interface Person {
    	public void speak();
    }











    展开全文
  • 匿名内部类

    千次阅读 多人点赞 2018-09-22 14:12:02
    一、匿名内部类:我看到很多人有提到“匿名内部类是没有名字的”,个人觉得用陈国君主编的《Java程序设计基础(第五版)》中的 “所谓匿名内部类,是指可以利用内部创建没有名称的对象,它一步完成了声明内部和...

    以下内容为笔者在学习过程中对相关知识点的理解和实践的记录,如有谬误,还请指出。

    一、匿名内部类:我看到很多人有提到“匿名内部类是没有名字的类”,个人觉得用陈国君主编的《Java程序设计基础(第五版)》中的 “所谓匿名内部类,是指可以利用内部类创建没有名称的对象,它一步完成了声明内部类和创建该类的一个对象,并利用该对象访问到类里面的成员”来描述,或许要更好理解一些。

    下面,我们来看一段代码:

    package lambdatest;
    public class InnerclassTest {  //外部类
        String name="黄林";
      public static void main(String []args){
          (
                  new InnerclassTest(){  //匿名内部类开始
                      void setName(String n){
                          this.name = n;
                          System.out.println("内部类---姓名:"+name);
                      }
                  }
                  ).setName("王佳");      //匿名内部类结束
      }
      
    }

    这是它的运行结果:

    这里的内部类是直接用外部类InnerclassTest的名字new一个对象,并紧接着定义类体的,这个内部类没有自己的名字,甚至将创建对象的工作直接交给了其父类InnerclassTest(在这里InnerclassTest既是一个外部类,也是匿名内部类的父类),在匿名内部类中重新给其父类成员name赋值,所以最后的结果是匿名内部类中所给的值将其父类成员变量的初始值给覆盖了。

    匿名内部类不需要class关键字,自然也不需要public,private等修饰,它没有构造方法,一般用来补充内部类中没有定义的内容,或者实现外部接口或其抽象父类中的抽象方法,这样使代码更加简短。比如上面的代码就为其外部类中的成员name属性添加了setName()方法,并利用匿名内部类对象调用该方法并为name赋值。

    编译之后所产生的字节码文件如下:

    package lambdatest;
    public class InnerclassTest {
        String name="黄岚岚";
        void test(){
            System.out.println("这是外部类中的方法~");
        }
      public static void main(String []args){
    
          (
                  new InnerclassTest(){
                      void setName(String n){
                          this.name = n;
                          System.out.println("内部类---姓名:"+name);
                      }
                      void test(){
                          System.out.println("这是内部类中Test方法的输出结果,看看我会不会覆盖外部类中的方法~"+name);
                      }
                  }
    //              ).setName("王佳");
          ).test();
      }
    
    }

    这是它的运行结果:

    从运行结果来看,匿名内部类中的test()方法对其父类(外部类进行了覆盖),而name仍然是初值,没有改变。

    我们再看下面这段代码:

    package lambdatest;
    public class InnerclassTest {  //这是一个包含内部类的外部类
      public static void main(String []args){
          (
                  new Inner(){  //匿名内部类开始
                      void setName(String n){
                          this.name = n;
                          System.out.println("内部类---姓名:"+name);
                      }
                  }
                  ).setName("王佳"); //匿名内部类结束
      }
    
      static class Inner{  //这是一个普通的内部类,,,mian方法是static的,这里不加static会出错,报错信息见下图
          String name="黄岚岚";
        }
    }

    在上面的代码中,包含了一个内部类Inner和用Inner来创建的匿名内部类,其中,Inner是InnerclassTest的一个成员内部类。

    因为从文件管理的角度看,内部类在编译完成之后,所产生的文件名为:“外部类名$内部类名.class”;

                                                    匿名内部类在编译完成之后,所产生的文件名为:“外部类名$编号.class”;

    下图为编译完成之后所产生的三个字节码文件:

    内部类:一个类定义在另一个类的内部。其中,内部类又可以分为成员内部类(定义在外部类中,与其它外部类中的属性、方法同级)和局部内部类(定义在外部类的方法里面)

    package lambdatest;
    public class InnerclassTest {
        public static void main(String []args) {
            Inner i = new Inner() {
                //  static int aa;             //匿名内部类中不允许出现静态属性
            void test () {
                System.out.println("这是匿名内部类,运行看会发生什么");
            }
            void haha(){   //如果父类中没有定义该方法,就不能通过父类对象来访问子类特有的方法
                System.out.println("hahahahahahahhahahahahah~");
            }
    
    //        static void hi(){    //匿名内部类中不允许出现静态方法
    //
    //        }
    
        };
            i.test();
            System.out.println(i.name);
    //        ((Inner) i).haha();
        }
    
        static class Inner{  //mian方法是static的,这里不加static会出错
            String name="黄岚岚";
            void test(){
                System.out.println("这是内部类");
            }
    //        void haha(){
    //            System.out.println("hahahahahahahhahahahahah~");
    //        }
        }
    }

    这里的写法跟上面的不太一样,但仔细看一下,其实是用成员内部类Inner实例化了一个对象 i ,在这里,Inner就变成了那个利用Inner来创建的匿名内部类的父类。

    要通过父类对象访问子类的成员,只限于“覆盖”的情况发生时。即子类中的成员test()对父类中同名且参数个数相同(都是无参)的test()进行了覆盖;如果释放 ((Inner) i).haha(); 则会出现错误,因为其父类Inner中并没有定义 haha()方法,所以不能通过其父类对象i去访问子类中特有的方法。

    在这里,因为i是父类Inner的实例化对象,所以用i访问不到匿名内部类中的haha()方法。再次强调:i时Inner的对象,不是匿名内部类的,访问不了匿名内部类的特有方法,只能覆盖。

    接着我们看看用匿名内部类实现接口的情况:

    package lambdatest;
    public class InnerclassTest {  //外部类
        
      public static void main(String []args){
    
          (
                  new Inner(){  //匿名内部类开始
                      public void test(){  //不用public修饰不通过,修饰范围>=接口才能覆盖
                          System.out.println("这是外部类接口中Test方法的实现类~"+name);
                      }
                  }
          ).test(); //匿名内部类结束
      }
    
       interface Inner{  //定义一个接口
           String name="黄岚岚";   // 默认public static final  ,值只能赋一次,且必须赋初值
          void test(); //默认用 public abstract修饰
        }
    }
    

    在上面的代码中,在InnerclassTest中定义了一个特殊的内部类------Inner接口(接口是一个特殊的抽象类),里面有一个属性name和一个抽象方法test();同样,用Inner接口new了一个匿名内部类,并实现了它里面的抽象方法test();

    package lambdatest;
    public class InnerclassTest {  //外部类
        String aa="ccccc";
        public void Aa(){
            System.out.println("aaaaaa");
        }
        public static void main(String []args){
            (
                    new InnerclassTest(){   //匿名内部类开始,继承InnerclassTest
                        public void Aa(){
                            System.out.println("bbbbbbbbbb"+aa);
                        }
                    }
            ).Aa();  //匿名内部类结束
    
            (
                    new Inner(){  //匿名内部类开始,实现Inner接口
                        public void test(){
                            System.out.println("匿名-------------~"+name);
                        }
                    }
            ).test(); //匿名内部类结束
        }
    
        interface Inner{    //定义一个接口
            String name="黄岚岚";
            void test();
        }
    }
    

    上面的代码则定义了一个外部类,并在里面定义了一个接口Inner以及分别用他们创建了一个匿名内部类。

    读到这里,相信你们也都看出来了,内部类继承一个类不需要extends修饰,实现一个接口也不需要implements,因为匿名内部类本身没有自己的名字,它的定义与创建该类的实例是同时进行的,也就是说它的前面用new运算符,而不是class关键字,用其父类名或父接口名加上一个"()"就完成了匿名对象的创建。

    在这里,InnerclassTset是它们(两个匿名内部类和一个匿名内部类)的外部类,而InnerclassTset对应的匿名内部类继承了InnerclassTset,Inner对应的匿名内部类则实现了Inner接口,也就是说,用谁来创建匿名内部类,就继承(或实现)谁。

    创建匿名内部类并访问其成员的语法格式为:

    (
    
    new 类名或接口名()   // ()中不能有参数
    
    {
    
    方法名(参数1,参数2,……)
    
    {
    
    //方法体
    
    }
    
    }
    
    ).方法名(参数1,参数2,……);

    为什么在类(接口)名后的"()"中不能带有参数呢?

    首先我们简单了解什么是构造方法:

    构造方法:(下面这句话是从https://baike.so.com/doc/1017212-1075815.html抄来的)

    构造方法是一种特殊的方法,它是一个与类同名且返回值类型为同名类类型的方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法。构造方法和其他方法一样也可以重载。因为匿名内部类没有名字,故,它本身没有构造方法,所以也就无法定义带参数的构造函数,因而,在new 一个匿名内部类的时候不可以带上参数。

    匿名内部类虽然没有自己的构造方法,但它可以访问其父类的构造方法:

    package lambdatest;
    public class InnerclassTest {      //外部类
        public void InnerclassTest(){
            System.out.println("ffffffffffffff");
        }
        String aa="ccccc";
        public void Aa(){
            System.out.println("aaaaaa");
        }
        public static void main(String []args) {
            InnerclassTest in=new InnerclassTest();
            in.InnerclassTest();
    
            InnerclassTest inct = (
                    new InnerclassTest() {
                        public void Aa() {
                            System.out.println("bbbbbbbbbb" + aa);
                        }
                    }
            );
            inct.Aa();
            inct.aa = "jjjj";
            inct.InnerclassTest();
            System.out.println("bbbbbbbbbb" + inct.aa);
        }
    }
    

    从产生的字节码文件来看,这里定义了一个外部类以及他的匿名内部类,在匿名内部类中对其父类的Aa()方法进行了覆盖,并利用内部类对象为aa重新赋值,但是笔者在这里还有个疑问(先记录一下。。):

    等我弄懂了再来补上好了。

    上面说了那么多,我无非是想弄清楚什么是匿名内部类以及证明匿名内部类与创建匿名内部类的类(或接口)之间是一种继承(或实现)关系,虽然书上一开始就提出了这一点,但我一直没弄明白(可能我理解能力比较差,爱钻牛角尖吧,QAQ),上面的内容纯属自己的理解,看到这边文章并且发现有什么不对的或者遗漏的,还请指出来。

    现在让我们来总结一下,匿名内部类必须实现一个接口或者继承一个类,不用class修饰,也不需要public,private,protected,static 等修饰;没有类名,也没有构造方法,在匿名内部类里面不能定义静态的属性和方法,只能实例化一次(因为匿名内部类的创建和实例化是同时进行的);匿名内部类其实可以看做是其外部类的一个成员,所以在匿名内部类中可以获取声明为private static 的属性的值,如下面的代码中,同样可以获取到aa的值的(这里跟单纯地继承一个类又有点不同了,因为如果只是继承,是无法获取父类中私有成员的值,也无法访问到父类私有方法的)

    package lambdatest;
    public class InnerclassTest {  //外部类
        private static String aa = "ccccc";
        public  void Aa() {
            System.out.println("aaaaaa");
        }
    
        public static void main(String[] args) {
            InnerclassTest ict=new InnerclassTest();
            (
                    new InnerclassTest() {   //匿名内部类开始,继承InnerclassTest
    
                        public void Aa() {
                            System.out.println("bbbbbbbbbb" + aa);
                        }
                    }
            ).Aa();  //匿名内部类结束
    
        }
    }

    应用场景:

    ①只需要实例化一次,并且想使代码看起来精简时;

    ②在Java的窗口程序设计中,用来编写“事件”的程序代码

     

    展开全文
  • 前端时间在写.net项目中,一直错将.cs里的两个class当作内部,原来是一个文件里的两个而已,这让我想起了Java中的内部,比较内部,那么还有两个,那就是匿名匿名内部类。今天我想就Java中的这三种类...

    前端时间在写.net项目中,一直错将.cs里的两个class当作内部类,原来是一个文件里的两个类而已,这让我想起了Java中的内部类,比较内部类,那么还有两个类,那就是匿名类和匿名内部类。今天我想就Java中的这三种类进行个比较。

    我们知道在Java语言规范中可以做很多事,例如一个类或一个接口中可以声明一个类或接口,在一个方法中可以声明一个类,类与接口声明可以嵌套任意深度等。

     

    匿名类:

          1、new <类或接口><类的主体>,匿名类的声明是在编译时进行的,实例化是在运行时进行的,所以在for循环中一个new语句会创建相同匿名类的几个实例,而不是创建几个不同匿名类的一个实例。

          2、如果要执行的对象需要一个对象,但却不值得创建全新的对象(可能是因为该对象只在一个方法内部使用),在这个时候使用匿名类就会非常合适,所以说,匿名类一般会在swing程序中快速创建事件处理程序。

    Java代码   收藏代码
    1. firstButton.addActionListener(new ActionListener() {  
    2.         @Override  
    3.         public void actionPerformed(ActionEvent e) {  
    4.             getTxtValue().setText("第一个按钮触发的事件!");  
    5.         }  
    6.     });   

           3、从技术上说,匿名类可以被看作非静态的内部类,所以他们具有方法内部声明的非静态内部类相同的权限和限制。

     

     

    内部类:

    内部类顾名思义就是在一个类的内部还有一个类

    Java代码   收藏代码
    1. package com.iflytek.innerclass;  
    2.   
    3. /** 
    4.  * @author xudongwang 2012-1-11 
    5.  *  
    6.  *         Email:xdwangiflytek@gmail.com 
    7.  */  
    8. public class InnerClassDemo {  
    9.     public static void main(String[] args) {  
    10.         new Outer().fun();  
    11.     }  
    12. }  
    13.   
    14. class Outer {  
    15.   
    16.     private String name = "Hello 内部类";  
    17.   
    18.     class Inner {  
    19.         public void print() {  
    20.             System.out.println("name = " + name);  
    21.   
    22.         }  
    23.     };  
    24.   
    25.     public void fun() {  
    26.         new Inner().print();  
    27.     }  
    28. }  

     

     内部类生成的.class文件名为:Outer$Inner.class,从上面的结构发现内部类的的缺点是“结构非常的混乱”。

    Java代码   收藏代码
    1. package com.iflytek.innerclass;  
    2.   
    3. /** 
    4.  * @author xudongwang 2012-1-11 
    5.  *  
    6.  *         Email:xdwangiflytek@gmail.com 
    7.  */  
    8. public class InnerClassDemo02 {  
    9.     public static void main(String[] args) {  
    10.         new Outer02().fun();  
    11.     }  
    12. }  
    13.   
    14. class Outer02 {  
    15.   
    16.     private String name = "Hello 内部类";  
    17.   
    18.     public void fun() {  
    19.         new Inner02(this).print();  
    20.     }  
    21.   
    22.     public String getName() {  
    23.   
    24.         return this.name;  
    25.     }  
    26. };  
    27.   
    28. class Inner02 {  
    29.     private Outer02 out;  
    30.   
    31.     public Inner02(Outer02 out) {  
    32.         this.out = out;  
    33.     }  
    34.   
    35.     public void print() {  
    36.         System.out.println("name = " + this.out.getName());  
    37.   
    38.     }  
    39. };  

     从上可以看出内部类的优点是“可以方便的访问外部类中的私有成员”;

    如果要在外部直接使用内部类的实例化对象:

          外部类.内部类 内部类对象 = 外部类实例.new 内部类实例();

    Java代码   收藏代码
    1. package com.iflytek.innerclass;  
    2.   
    3. /** 
    4.  * @author xudongwang  2012-1-11 
    5.  * 
    6.  *  Email:xdwangiflytek@gmail.com 
    7.  */  
    8. public class InnerClassDemo03 {  
    9.     public static void main(String[] args) {  
    10.         Outer03 out = new Outer03();//外部类实例  
    11.         Outer03.Inner inner = out.new Inner();//实例化内部类对象  
    12.         inner.print();  
    13.     }  
    14. }  
    15. class Outer03{  
    16.     private String name = "Hello 内部类";  
    17.     class Inner {  
    18.         public void print() {  
    19.             System.out.println("name = " + name);  
    20.         }  
    21.     }  
    22. }  

     

     一个内部类如果使用static关键字声明的话,则此内部类就将成为外部类,可以直接通过外部类.内部类的形式访问

    Java代码   收藏代码
    1. package com.iflytek.innerclass;  
    2.   
    3. /** 
    4.  * @author xudongwang 2012-1-11 
    5.  *  
    6.  *         Email:xdwangiflytek@gmail.com 
    7.  */  
    8. public class InnerClassDemo04 {  
    9.     public static void main(String[] args) {  
    10.         Outer04.Inner inner = new Outer04.Inner();// 实例化内部类对象  
    11.         inner.print();  
    12.     }  
    13. }  
    14.   
    15. class Outer04 {  
    16.     private static String name = "Hello 内部类";  
    17.   
    18.     static class Inner {  
    19.         public void print() {  
    20.             System.out.println("name = " + name);  
    21.         }  
    22.     }  
    23. }  

     

     内部类可以在任意的地方使用,例如方法中声明

    Java代码   收藏代码
    1. package com.iflytek.innerclass;  
    2.   
    3. /** 
    4.  * @author xudongwang 2012-1-11 
    5.  *  
    6.  *         Email:xdwangiflytek@gmail.com 
    7.  */  
    8. public class InnerClassDemo05 {  
    9.     public static void main(String[] args) {  
    10.         new Outer05().fun();  
    11.     }  
    12. }  
    13.   
    14. class Outer05 {  
    15.     private static String name = "Hello 内部类";  
    16.   
    17.     public void fun() {  
    18.         class Inner {  
    19.             public void print() {  
    20.                 System.out.println("name = " + name);  
    21.             }  
    22.         }  
    23.         new Inner().print();  
    24.     }  
    25. }  

     

     在方法中定义的内部类,可以直接访问外部类中的各个成员,但是如果要访问方法中的参数,则需要在参数上加上final关键字声明;

    Java代码   收藏代码
    1. package com.iflytek.innerclass;  
    2.   
    3. /** 
    4.  * @author xudongwang 2012-1-11 
    5.  *  
    6.  *         Email:xdwangiflytek@gmail.com 
    7.  */  
    8. public class InnerClassDemo06 {  
    9.     public static void main(String[] args) {  
    10.         new Outer06().fun(20);  
    11.     }  
    12. }  
    13.   
    14. class Outer06 {  
    15.     private static String name = "Hello 内部类";  
    16.   
    17.     public void fun(final int temp) {  
    18.         class Inner {  
    19.             public void print() {  
    20.                 System.out.println("temp = " + temp);  
    21.                 System.out.println("name = " + name);  
    22.             }  
    23.         }  
    24.         new Inner().print();  
    25.     }  
    26. }  

     匿名类与内部的联系与区别:

    按所在位置可以分为两大类:

          1、在类的方法中

                         特点:

                                  a、可以访问宿主类的所有元素 ;

                                  b、保存宿主类对象的引用,创建对象时必须有宿主类对象;

                                  c、 不能有静态数据;

    继续划分:

                                 A、本地内部类;

                                 B、匿名内部类

     两者的区别在于本地内部类有构造方法,而匿名内部类只能实例初始化;

          2、在类或接口作用域中;

                         继续划分:

                                A、普通内部类

                                B、静态内部类

     

     

    匿名内部类:

    匿名内部类是在抽象类和接口的基础之上发展起来的。

    Java代码   收藏代码
    1. package com.iflytek.innerclass;  
    2.   
    3. /** 
    4.  * @author xudongwang 2012-1-11 
    5.  *  
    6.  *         Email:xdwangiflytek@gmail.com 
    7.  */  
    8. public class NoNameClass01 {  
    9.     public static void main(String[] args) {  
    10.         new X().fun2();  
    11.     }  
    12. }  
    13.   
    14. interface A {  
    15.     public void fun();  
    16. }  
    17.   
    18. class B implements A {  
    19.     public void fun() {  
    20.   
    21.         System.out.println("Hello 准备匿名内部类");  
    22.     }  
    23. }  
    24.   
    25. class X {  
    26.     public void fun1(A a) {  
    27.         a.fun();  
    28.     }  
    29.   
    30.     public void fun2() {  
    31.         this.fun1(new B());  
    32.     }  
    33. }  

     通过上面的Demo,如果现在假设B类只使用一次,那么还有必要将其定义成一个单独的类么?

     呵呵,此时就可以使用匿名内部类:

    Java代码   收藏代码
    1. package com.iflytek.innerclass;  
    2.   
    3. /** 
    4.  * @author xudongwang 2012-1-11 
    5.  *  
    6.  *         Email:xdwangiflytek@gmail.com 
    7.  */  
    8. public class NoNameClass02 {  
    9.   
    10.     public static void main(String[] args) {  
    11.         new XX().fun2();  
    12.     }  
    13. }  
    14.   
    15. interface AA {  
    16.     public void fun();  
    17. }  
    18.   
    19. class XX {  
    20.     public void fun1(AA a) {  
    21.         a.fun();  
    22.     }  
    23.     public void fun2() {  
    24.         this.fun1(new AA() {  
    25.             public void fun() {  
    26.                 System.out.println("Hello 准备匿名内部类");  
    27.             }  
    28.         });  
    29.     }  
    30. }  

     其实在真正的项目开发中匿名内部类使用的非常之少,一般在Java的图形界面和现在的Android中使用的比较多点。

     

     最后给一个内部类实现的简单链表:

    Java代码   收藏代码
    1. package com.iflytek.innerclass;  
    2.   
    3. /** 
    4.  * @author xudongwang 2012-1-11 
    5.  *  
    6.  *         Email:xdwangiflytek@gmail.com 
    7.  */  
    8. public class LinkDemo {  
    9.     public static void main(String args[]) {  
    10.         Link link = new Link();  
    11.         link.add("A");  
    12.         link.add("B");  
    13.         link.add("C");  
    14.         link.add("D");  
    15.         link.add("E");  
    16.         link.print();  
    17.     }  
    18. };  
    19.   
    20. class Link {  
    21.     class Node {  
    22.         private String name;  
    23.         private Node next; // 单向链表,每个节点指向下一个节点  
    24.   
    25.         public Node(String name) {  
    26.             this.name = name; // 通过构造方法为name属性赋值  
    27.         }  
    28.   
    29.         public void addNode(Node newNode) { // 增加节点  
    30.             if (this.next == null) {  
    31.                 this.next = newNode; // 保存节点  
    32.             } else {  
    33.                 this.next.addNode(newNode); // 继续向下查找  
    34.             }  
    35.         }  
    36.   
    37.         public void printNode() { // 输出节点  
    38.             System.out.println(this.name);  
    39.             if (this.next != null) { // 此节点之后还存在其他的节点  
    40.                 this.next.printNode();  
    41.             }  
    42.         }  
    43.     };  
    44.   
    45.     private Node root; // 链表的头  
    46.   
    47.     public void add(String name) { // 增加节点  
    48.         Node newNode = new Node(name); // 定义一个新的节点  
    49.         /* 
    50.          * 如果是第一个节点,则肯定是根节点, 如果是第二个节点,则肯定放在根节点next中 如果是第三个节点,则肯定放在第二个节点的next中 
    51.          */  
    52.         if (this.root == null) {  
    53.             this.root = newNode; // 将第一个节点设置成根节点  
    54.         } else {  
    55.             // 肯定要放在最后一个节点之后  
    56.             // 通过节点.next来不断的判断  
    57.             this.root.addNode(newNode);  
    58.         }  
    59.     }  
    60.   
    61.     public void print() {  
    62.         if (this.root != null) { // 如果根节点为空了,则没有任何内容  
    63.             this.root.printNode();  
    64.         }  
    65.     }  
    66. };  





    展开全文
  • Java 匿名(匿名内部类)

    千次阅读 2020-12-25 23:41:48
    Java匿名(匿名内部类) 学习的参考博文:无恨之都 1. 初识 匿名 标准说法: 内部包括:成员、局部、匿名(匿名内部类)。 匿名概念: 匿名类可以使你的代码更加简洁 (JDK8之后Lambda更简洁)。 你可以...

    Java 匿名类(匿名内部类)

    学习的参考博文:无恨之都

    1. 初识 匿名类

    标准说法: 内部类包括:成员类、局部类、匿名类(匿名内部类)。

    匿名类概念:

    • 匿名类可以使你的代码更加简洁 (JDK8之后Lambda更简洁)。
    • 你可以定义一个类的同时对其进行实例化
    • 它与局部类很相似,不同的是它没有类名,如果某个局部类你只需要使用一次,就可以使用匿名类代替局部类
    • 匿名类是表达式,而非常规的类

    匿名类的使用场景:

    • 一个局部类只需要使用一次的时候
    • 由于匿名类没有类名,那么除了定义它的地方,其他地方无法调用,所以匿名类也可以叫匿名内部类

    2. 通过示例分析局部类和匿名类区别

    sayHello方法中有局部类和匿名类分别实现HelloWorld接口的方法

    public class HelloWorldAnonymousClasses {
    
        interface HelloWorld {
            public void greet();
            public void greetSomeone(String someone);
        }
    
        public void sayHello() {
    
            /**
             * 1、局部类:EnglishGreeting实现了HelloWorld接口
             */
            class EnglishGreeting implements HelloWorld {
                String name = "无参";
                @Override
                public void greet() {
                    greetSomeone(name);
                }
                @Override
                public void greetSomeone(String someone) {
                    name = someone;
                    System.out.println("局部类:" + name);
                }
            }
            // 创建局部类EnglishGreeting的实例化对象,使用接口类型接收
            HelloWorld englishGreeting = new EnglishGreeting();
            // 局部类:无参方法
            englishGreeting.greet();
            // 局部类:带参方法
            englishGreeting.greetSomeone("带参");
    
    
            /**
             * 2、匿名类实现HelloWorld接口并创建了实例化对象:frenchGreeting
             */
            HelloWorld frenchGreeting = new HelloWorld() {
                String name = "无参";
                @Override
                public void greet() {
                    greetSomeone(name);
                }
                @Override
                public void greetSomeone(String someone) {
                    name = someone;
                    System.out.println("匿名类:" + name);
                }
            };
    
            // 匿名类:无参方法
            frenchGreeting.greet();
            // 匿名类:带参方法
            frenchGreeting.greetSomeone("带参");
        }
    
        public static void main(String... args) {
            HelloWorldAnonymousClasses myApp = new HelloWorldAnonymousClasses();
            myApp.sayHello();
        }
    

    【输出】

    局部类:无参
    局部类:带参
    匿名类:无参
    匿名类:带参
    

    【分析】
      代码里局部类和匿名类实现的功能是一样的,内部的方法实现的代码是也一样的,区别只在实现HelloWorld接口的地方

    局部类的格式是:

    1. 创建局部类并且实现接口:class EnglishGreeting implements HelloWorld {...}
    2. 创建局部类的实例化对象并用接口类型接收:HelloWorld englishGreeting = new EnglishGreeting();
    3. 调用实例化对象的方法

    匿名类的格式是:

    1. 创建匿名类实现接口同时对其进行实例化:HelloWorld frenchGreeting = new HelloWorld() {...}
    2. 调用实例化对象的方法

    【区别】

    1. 局部类EnglishGreeting实现HelloWorld接口,有自己的类名:EnglishGreeting,定义完成后需要再对其实例化对象:englishGreeting才能可以使用方法
    2. 匿名类在定义时就已经实例化成对象:frenchGreeting,定义完了就可以直接使用方法
    3. 匿名类是一个表达式,因此在定义的最后用分号结束

    3. 匿名内部类的语法

    3.1 匿名类实现接口

    其实上面的示例中的匿名类就是实现接口的方式,这个示例将实现更复杂的功能

    public class InterfaceTest {
        public static void main(String[] args) {
            TomInterface tif = new TomInterface() {
                String name = "汤姆";
                @Override
                public void getName() {
                    System.out.println(name);
                }
    
                TomInterface setName(String name){
                    this.name = name;
                    return this;
                }
            }.setName("杰瑞");
            tif.getName();
        }
    }
    
    interface TomInterface{
        void getName();
    }
    

    【结果】

    杰瑞
    

    【分析】

    1. main方法创建匿名类实现TomInterface接口并实例化:new TomInterface{...}
    2. 调用匿名类对象的setName方法,将杰瑞赋值给匿名类的成员变量name,并返回当前实例this给接口变量tif
    3. main方法调用匿名类对象的方法tif.getName(),而此时的匿名类的成员变量name的值已经被替换成杰瑞,所以最后输出杰瑞而不是汤姆

    3.2 匿名类继承父类 (匿名子类)

    匿名类继承父类,调用父类构造,重写父类方法

    public class ExtendTest {
    
        public static void main(String[] args) {
            String name = "李四";
            // 创建父类对象,打印原始name值
            PartherClass partherClass = new PartherClass();
            System.out.println("父类的getName方法=" + partherClass.getName());
            // 使用匿名类继承父类,并打印name值
            PartherClass pc = new PartherClass(name){
                @Override
                public String getName(){
                    return "匿名类 - "+super.getName();
                }
            };
            System.out.println(pc.getName());
        }
    }
    
    class PartherClass{
        private String name = "张三";
        public PartherClass(){}
        public PartherClass(String name){
            this.name = name;
        }
        public String getName(){
            return this.name;
        }
    }
    

    【结果】

    父类的getName方法=张三
    匿名类 - 李四
    

    【分析】

    1. 创建父类对象并调用getName方法,这个不用细说
    2. 创建匿名类继承父类并实例化对象:pc,本次匿名类调用的是父类的带参构造,将参数赋值给了父类的name
    3. 调用匿名类重写的getName方法,得到新的name

    3.3 区别

    Demo demo = new Demo(xxx){...}
    
    1. 操作符:new
    2. 一个要实现的接口或要继承的类,示例3.1 是实现接口,示例3.2 是继承类
    3. 一对括号,如果是匿名子类,那么父类有构造参数就填,不带参就空着;如果匿名类是实现接口,那么括号里需要空着
    4. {...},括号里括着的是匿名类的声明主体
    5. 末尾的;号,因为匿名类的声明是一个表达式,是语句的一部分,所以需要分号结尾
    6. 表面上看匿名类没有类名,没有构造参数。但其实在编译的时候,编译器会给匿名类分配类名和构造器,只是我们无法操作也不能复用。如需验证,可以看编译后的class文件,多出一个命名格式:匿名类定义类$?.class的文件。例如示例3.2,匿名类的class文件就是:ExtendTest$1.class
    展开全文
  • Java 内部分四种:成员内部、局部内部、静态内部匿名内部类
  • 分四种:成员内部、局部内部、静态内部匿名内部类。 1、成员内部: 即作为外部的一个成员存在,与外部的属性、方法并列。 注意:成员内部中不能定义静态变量,但可以访问外部的所有成员。 public ...
  • 【50】java 匿名内部类剖析

    千次阅读 2016-05-26 16:10:55
    匿名内部类介绍: ...匿名内部类声明格式如下: new ParentName(){ ...// 内部的定义 } 匿名内部类的使用场景: .只用到的一个实例 。 ·在定义后马上用到。 ·非常小(SUN推荐...
  • 内部类(inner class) 内部类顾名思义就是,定义在中的。我们常说的内部类就是最普通的内部类,而非局部匿名静态的。...内部类可以访问外部的方法和属性,即使他们是私有的,而且内部类对于同一...
  • Java基础笔记 – 内部 静态内部 成员内部 局部内部 匿名内部类 本文由包小卷发表于2年前 | Java基础 | 评论关闭 | 被围观 2,995 views+ 内部: 使用内部减少了命名冲突。 一个内部类可以定义在一个...
  • Java匿名内部类及应用

    2019-02-17 18:36:55
    2.匿名内部类必须继承一个(抽象,非抽象的都可以)或者实现一个接 口。如果父类(父接口)是抽象的,则匿名内部类必须实现其所有抽象方法。 3.匿名内部类可以定义代码块,用于实例的初始化,但是不能定义 静态代码...
  • Java 内部匿名内部类、抽象

    千次阅读 2016-07-28 22:50:51
    何为内部类内部类是指 在一个中在定义一个 如: 1.成员内部类public class F { private int a; public void fun(){ //TODO } public class M{ private int a; public void fun(){ //TODO
  • 成员内部类可以随意使用外部的成员方法及成员变量,尽管这些成员被修饰为private.内部类的实例一定要绑定在外部对象上。 一个内部类可以定义在一个中,一个方法中甚至一个表达式中。 分类: 内部类
  • //声明一个接口供匿名内部类使用,也可以是抽象ps:如果是的话扩充的方法和变量 interface A { public void p(); } public class InnerClass { // 非静态方法 private final String name = "Inner"; /...
  • 分四种:成员内部、局部内部、静态内部匿名内部类。 1、成员内部: 即作为外部的一个成员存在,与外部的属性、方法并列。 注意:成员内部中不能定义静态变量,但可以访问外部的所有成员。 public ...
  • JAVA8 匿名内部类和lambda表达式

    万次阅读 多人点赞 2017-07-16 19:29:30
    一.匿名内部类  匿名内部类适合创建那种只需要一次使用的,例如前面介绍命令模式时所需要的Command对象,匿名内部类的语法有点奇怪,创建匿名内部类时会立即创建一个该的实例,这...从上面可以看出,匿名内部类
  • 内部:内部分为四种: 1、静态内部(static inner classes)1.1、相关使用例子:2、... inner classes):3.1、相关使用例子:4、匿名内部类(anonymous inner classes):4.1、相关使用例子: 内部
  • 分四种:成员内部、局部内部、静态内部匿名内部类。  1、成员内部: 即作为外部的一个成员存在,与外部的属性、方法并列。 注意:成员内部中不能定义静态变量,但可以访问外部的所有成员。 public...
  • lambda表达式与匿名内部类

    万次阅读 2020-08-07 14:13:01
    Lambda表达式类似匿名函数,简单地说,它是没有声明的方法,也即没有访问修饰符、返回值声明和方法名。 Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中)。 Lambda表达式的语法 (parameters) -> ...
  • java内部 匿名内部类

    千次阅读 2013-11-15 22:20:52
     1、new ,匿名类声明是在编译时进行的,实例化是在运行时进行的,所以在for循环中一个new语句会创建相同匿名类的几个实例,而不是创建几个不同匿名类的一个实例。  2、如果要执行的对象需要一个对象,但却不...
  • 前言自己看了一眼oracle官网关于内部类的介绍, 不多, 但是有些点还是要注意的. 当然这些知识只能说是面试有用, 平时使用内部类, 如果违反规则, 编译器会提示你的, 所以看看就行, 没必要背熟.名词介绍先把我们用的...
  • 在使用匿名内部类时,要记住以下几个原则:  · 匿名内部类不能有构造方法。 (因为匿名内部类是没有类名的)  · 匿名内部类不能定义任何静态成员、方法和。... · 匿名内部类不能是public,protected,private,
  • 匿名内部类是否可以由静态的内容

    千次阅读 2017-07-27 11:05:12
    理由:匿名内部类是晚于外部加载的,但是匿名内部类和其对象几乎是同时加载的,但是还是早于对象加载,而静态内容是属于的,当加载的时候就开始加载,所以当匿名内部类中有静态内容,就会随着加载,而这时和...
  • 如题,在实际开发中,关于静态、静态方法、内部匿名内部类、非静态一般都会遇到,特别是你在研究开源框架源码的时候很是常见,它是内聚性的体现。本文针对这些“概念”的实战,做些总结。
  • 1.18 Java匿名匿名内部类

    千次阅读 2020-09-30 13:12:36
    匿名类是指没有类名的内部类,必须在创建时使用 new 语句来声明类。其语法形式如下: new <或接口>() { // 的主体 }; 这种形式的 new 语句声明一个新的匿名类,它对一个给定的进行扩展,或者实现一个...
  • 以前Android开发的时候,有时候会看到内部比如定义Adapter的ViewHolder和匿名内部类比如各种事件等。但是对于内部匿名内部类的概念以及里面的一些细节却比较模糊,如今我总结如下:概念内部是定义在中的...
  • JAVA匿名内部类的学习

    2013-03-15 18:05:40
    网上找了很多资料,学习了一下内部,其实也不常用,具体也没有怎么使用过,还是学习下了。 一般用在 事件处理、线程比较多 注意匿名声明是在编译时进行的,实例化在运行...匿名内部类不能定义任何静态成员、方法
  • Java:内部匿名内部类

    千次阅读 2019-05-24 13:54:33
    一: 什么是内部类(Java 内部类,成员,局部,匿名类等): 根据内部类的位置不同,可将内部类分为 1. 成员内部类 2. 局部内部类 class A{ //成员内部类 class B{ } public void show1() { //局部内部类 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 56,059
精华内容 22,423
关键字:

匿名内部类可以声明为private