精华内容
下载资源
问答
  • 内部详解————匿名内部类

    千次阅读 2018-05-05 13:14:29
    内部三连击: ...由于匿名内部类不利于代码的重用,因此,一般在确定此内部只会使用一次时,才会使用匿名内部类。 形式 public class OutterClass { public Runnable task() { return new Run...

    内部类三连击:

    内部类详解————匿名内部类

    内部类详解————局部内部类

    内部类详解————静态嵌套类

    应用场景

    由于匿名内部类不利于代码的重用,因此,一般在确定此内部类只会使用一次时,才会使用匿名内部类。

    形式

    public class OutterClass {
        public Runnable task() {
            return new Runnable() {
                @Override
                public void run() {
                    System.out.println("匿名内部类...");
                }
            };
        }
    }

    这种实现方式是不是很眼熟呢?

            // 初始化线程实例
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("匿名内部类...");
                }
            });

    我们为线程创建一个Runnable子类实例的方式,就是一种匿名内部类的写法。我们通过这种没有名字的类,实现了将实现类(下称子类)实例创建与子类定义结合在一起的优雅格式,这也就是所谓的“使用类的定义直接创建实例”。

    上面的代码是实现了Runnable接口,并重写了其中的run()方法,当然我们可以自己定义一个类(非接口)然后通过这种匿名内部类的方式来隐式的继承,并重写基类中的方法。

    不论是继承父类,还是实现接口,实际上拿到的是父类接口的引用。这个父类引用实际指向的是一个由匿名内部类定义的类的实例。因此,这个被继承的父类(或接口)必须是事先存在的。否则,编译器会提示你创建这个类。

    使用规则

    经过查阅资料和实操得出的匿名内部类的几条规则:

    规则一:匿名内部类中的方法都是通过父类引用访问的,所以,如果定义了一个在父类中没有的方法,那么这个方法是不能被这个父类引用调用到的。(可以仅仅作为匿名内部类中方法之间的代码共享)。

    规则二:匿名内部类既可以继承父类,也可以实现接口,但是不能两者兼备。而且如果实现接口也只能实现一个接口。

    规则三:匿名内部类中不可能有构造器。但可通过实例初始化块 来达到构造器的效果,但是也不能重载实例初始化方法(即仅有一个这样的“构造器”)。(关于实例初始化:《Java静态初始化,实例初始化以及构造方法》

    规则四:在匿名内部类中如果希望使用一个其外部定义的对象,那么编译器会要求其参数引用是final的。

    关于第四条规则,这里牵涉了一个重要的且比较复杂的问题。

    使用案例:

    /** 定义接口*/
    public interface MyInterface {
        void doSomething();
    }
    public class TryUsingAnonymousClass {
        // 外部类成员方法
        public MyInterface useMyInterface() {
            final int number = 201855;// jdk1.8后可以省略final
            final Object obj = new Object();// jdk1.8后可以省略final
            
            MyInterface myInterface = new MyInterface() {
                // 匿名内部类
                @Override
                public void doSomething() {
                    System.out.println("匿名内部类中使用基本数据类型:" + number);
                    System.out.println("匿名内部类中使用引用数据类型:" + obj);
                }
            };
            return myInterface;
        }
        
        public static void main(String[] args) {
            TryUsingAnonymousClass tc = new TryUsingAnonymousClass();
            MyInterface inter = tc.useMyInterface();
            inter.doSomething();
        }
    }

    输出:

    匿名内部类中使用基本数据类型:201855
    匿名内部类中使用引用数据类型:java.lang.Object@15db9742

    我们通过匿名内部类的方式实现了接口MyInterface,并使用了外部类的成员方法useMyInterface() 中定义的两个局部变量:

    int number = 201855;
    Object obj = new Object();

    (在jdk1.8之后,新增了effectively final功能,开发者可以不必显式地使用final关键字来修饰局部内部类或匿名内部类中用到的局部变量,由系统默认添加。)

    因此我们在匿名内部类中用到的局部变量必须为常量(对于基本类型,其值恒定不变;对于引用类型,其引用,即指向的地址恒定不变)。

    如果强行改值,则会报错(这是在1.8程序上未使用final定义number时的尝试,系统果然默认此值为final的):

    不得不引出的局部变量与匿名内部类实例生命周期问题

    我们知道成员方法中的局部变量是在运行期进行定义和初始化的,而局部内部类(包括匿名内部类)虽然是在方法中定义的,但是它却依然会在编译期实现从java文件到class文件的转化,即编译成class文件。

    编译期在前,运行期在后。而我们却要在编译期使用运行期定义的变量!

    怎么办?我们脑海中浮现了两个在编译期便能取得常量的相关关键字:static final  但显然,static无法定义局部变量。

    那final能为我们的程序带来什么?

    翻阅《Java编程思想》中对final关键字的剖析(第四版,140页):

    一个永不改变的编译时常量。

    《深入理解Java虚拟机:JVM高级特性与最佳实践》中(第二版,168页)对于Class文件常量池也做出了相关解释:

    常量池(博主注:此常量池为class文件常量池,非运行时常量池,两者最大的区别是后者具有动态性)
    中主要存放两大类常量:字面量和符号引用。字面量比较接近于Java语言层的常量概念,如文本字符串、声明为final的常量值等。

    匿名内部类被编译成了class文件,它将final定义的局部变量编译进了class文件的常量池中,因此,我们会看上面的代码:

    public static void main(String[] args) {
            TryUsingAnonymousClass tc = new TryUsingAnonymousClass();
            MyInterface inter = tc.useMyInterface();
            inter.doSomething();
        }

    int型局部变量number和Object类型obj在方法useMyInterface()执行完毕之后即结束了生命周期,但是在下面通过调用inter对象的doSomething()方法依然可以有效的输出这两个值,说明这两个常量并没有受到外部类方法执行完毕而导致局部变量生命周期结束的问题,实际上number和obj已经存在于匿名内部类对应的class文件中的常量池中。

    虽然final修饰的常量解决了在编译期拿到运行期的变量的问题,但是final带来的副作用是,这个值无法改变。

    对于需要改变局部变量值的情况,我们可以通过在匿名内部类中使用赋值的方式(学名:引用拷贝 =.0)来“接管”局部变量的值,然后我们就可以随意更改这个值了。

    综上,就是最近对匿名内部类的研究和讨论。结合了final关键字的用法和class文件常量池来多角度讨论匿名内部类的final常量问题。后期如果有什么新的理解还会继续更新。文中的错别字和排版不适感博主已经进行了纠错和修改,如果各位在阅读时发现了任何错误,都请在文末留言。

     

    展开全文
  • Java匿名内部类

    2017-03-05 18:11:35
    根据声明的位置,判断匿名内部类是成员内部还是方法内部。一般是方法内部,这是就具备内部特性
    根据声明的位置,判断匿名内部类是成员内部类还是方法内部类。一般是方法内部类,这是就具备内部类的特性
    展开全文
  • 3.1 匿名内部类特性   1. 匿名内部类总是默认实现某个接口或继承某个抽象。 2.不能有构造方法,只能有一个实例。 3. 不能定义在任何静态成员、静态方法。 4. 不能是public.protected.private static. 5. ...

    3. 匿名内部类

     

     没有名字的内部类就是匿名内部类。

     

    3.1 匿名内部类特性

     

    1. 匿名内部类总是默认实现某个接口或继承某个抽象类。

    2.不能有构造方法,只能有一个实例。

    3. 不能定义在任何静态成员、静态方法。

    4. 不能是public.protected.private static.

    5. 匿名内部类为局部的,所以局部内部类的所有限制都对其有效。

    3.2  匿名内部类的使用方式

    一、继承式的匿名内部类: 就是new 抽象类。

    示例:

    package 匿名内部类抽象类练习;
    
    public abstract class Tv {
    	//打开电视
    	public abstract void open();
    	
    	//关闭电视
    	public abstract void close();
    	
    	//换台
    	public abstract void turn();
    }
    
    package 匿名内部类抽象类练习;
    
    public class Summer {
    	public static Tv extendsTv() {
    		Tv tv = new Tv() {
    
    			@Override
    			public void open() {
    				System.out.println("打开三星电视...");
    				
    			}
    
    			@Override
    			public void close() {
    				System.out.println("关闭三星电视...");
    				
    			}
    
    			@Override
    			public void turn() {
    				System.out.println("对三星电视进行换台...");
    				
    			}
    			
    		};
    		
    		//tv.open();
    		//tv.close();
    		//tv.turn();
    		return tv;
    	}
    }
    package 匿名内部类抽象类练习;
    
    public class XiaoMi {
    	public static Tv extendsTv() {
    		//匿名内部类... 抽象类的实现 ...
    		Tv tv = new Tv() {
    
    			@Override
    			public void open() {
    				System.out.println("打开小米电视...");
    				
    			}
    
    			@Override
    			public void close() {
    				System.out.println("关闭小米电视...");
    				
    			}
    
    			@Override
    			public void turn() {
    				System.out.println("对小米电视进行换台...");
    				
    			}
    			
    		};
    		
    		//tv.open();
    		//tv.close();
    		//tv.turn();
    		
    		return tv;
    	}
    }
    package 匿名内部类抽象类练习;
    
    public class Test {
    	public static void main(String[] args) {
    		Tv xiaomi = XiaoMi.extendsTv();
    		xiaomi.open();
    		xiaomi.turn();
    		xiaomi.close();
    		
    		System.out.println("------------------------------");
    		
    		Tv summer = Summer.extendsTv();
    		summer.open();
    		summer.turn();
    		summer.close();
    	}
    }

     

    展开全文
  • 内部匿名内部类

    2014-03-26 23:06:28
    一、内部类的访问规则: 1. 内部类可以直接访问外部中的成员,包括私有;是因为内部类持有了外部的引用。格式:外部.this。 2. 外部要访问内部类必须建立内部类对象。 class Outer { private int x = ...

    一、内部类的访问规则:

    1. 内部类可以直接访问外部类中的成员,包括私有;是因为内部类持有了外部类的引用。格式:外部类.this。

    2. 外部类要访问内部类必须建立内部类对象。

    class Outer {
    	private int x = 3;
    	
    	class Inner {
    		int x = 4;
    		
    		void function() {
    			int x = 5;
    			System.out.println("Inner:"+x);//5
    			System.out.println("Inner:"+this.x); //4
    			System.out.println("Inner:"+Outer.this.x); //3
    		}
    	}
    }
    二、内部类的访问规则:

    1. 当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中建立内部类对象。

    格式:外部类.内部类 对象名 = new 外部类().内部类();

    Outer.Inner in = new Outer.Inner();

    2.当内部类在成员位置上,就可以被成员修饰符所修饰。

    比如,private:将内部类在外部类中进项封装;static:内部类就具备了static特性,当内部类被static修饰后,只能直接访问外部类中的静态成员。出现了访问局限。

    在外部其他类中,如何直接访问static内部类的非静态成员呢?

    newOuter.Inner().function();

    在外部其他类中,如何访问静态内部类的静态成员呢?

    Outer.Inner.function();

    注意:

    当内部类中定义了静态成员,该内部类必须是static的。

    当外部类中的静态方法访问内部类时,内部类也必须是static。

    3. 内部类定义在局部时,

    (1). 不可以被成员修饰符修饰

    (2). 可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问他所在的局部中的变量,只能访问被final修饰的局部变量。

    三、什么时候使用内部类

    当描述事物时,事物的内部还有事物,该事物用内部类来描述。

    class Outer {
    	int x = 3;
    	
    	void method() {
    		final int y = 4;
    		
    		class Inner {
    			void function() {
    				System.out.println(y);
    			}
    		}
    		new Inner().function();
    	}
    }
    四、匿名内部类

    1.匿名内部类其实就是内部类的简写格式。

    2.定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。

    //继承外部类
    abstract class AbsDemo {
    	abstract void show();
    }
    
    class Outer {
    	int x = 3;
    	class Inner extends AbsDemo {
    		void show() {
    			System.out.println("show:"+x);
    		}
    	}
    	public void function() {
    		new Inner().show();
    	}
    }
    
    class InnerDemo {
    	public static void main(String[] args) {
    	new Outer().function();
    	}
    }

    //匿名内部类
    abstract class AbsDemo {
    	abstract void show();
    }
    class Outer {
    	int x = 4;
    	
    	void functoin() {
    		new AbsDemo() {
    			void show() {
    			System.out.println("functoin run");
    			}
    		};
    	}
    }
    
    public class InnerDemo<span style="font-family: Arial, Helvetica, sans-serif;"> </span>{
    	public static void main(String[] args) {
    	new Outer().functoin();
    	}
    }

    new Inner().method();因为没有Inner类所以用父类AbsDemo替代,实现抽象方法,再调用show()方法。

    3.匿名内部类的格式: new 父类或者接口() {定义子类的内容}

    4.其实匿名内部类就是一个匿名子对象,而且这个对象有点胖。可以理解为带内容的对象。

    5.匿名内部类中定义的方法最好不要超过三个。

    注意:没有父类和实现接口也可以有匿名内部类

    //没有父类和实现接口也可以有匿名内部类
    public class InnerTest {
    	public static void main(String[] args) {
    		new Object() {
    			void function() {
    				System.out.println("function run");
    			}
    		}.function();
    	}
    }
    展开全文
  • 作用:对匿名内部类的简化。 写法:3种。 (参数) -> 单行语句 (参数) -> { 多行语句 } (参数) -> 表达式 测试代码: public class Test05 { public static void main(String[] args) { // 使用匿名内部...
  • 匿名内部类就是内部和匿名的结合!! 内部详解 1、定义  一个的定义放在另一个的内部,这个就叫做内部。 public class First { public class Contents{ public void f(){ System.out....
  • java匿名内部类和lambda(匿名方法)

    千次阅读 2019-07-28 13:05:21
    匿名内部类 内部分4种:成员内部,静态内部,局部内部匿名内部类。我们今天讨论的就是其中最常见的匿名内部类。从名称可以看出,就是没有名字的,因为没有名字,所以总归和其它普通有一些些区别: ...
  • 匿名内部类特点及注意

    千次阅读 2017-10-09 12:17:52
    匿名内部类也就是没有名字的内部,无class关键字,直接使用new来生成一个对象的引用正因为没有名字,所以匿名内部类只能使用一次 匿名内部类还有个前提条件:必须继承一个父类(抽象,普通)或实现一个接口...
  • JAVA8 匿名内部类和lambda表达式

    万次阅读 多人点赞 2017-07-16 19:29:30
     匿名内部类适合创建那种只需要一次使用的,例如前面介绍命令模式时所需要的Command对象,匿名内部类的语法有点奇怪,创建匿名内部类时会立即创建一个该的实例,这个的定义立即消失,匿名内部类不能重复使用...
  • 有些情况下,我们把一个放在另一个内部定义,称为内部类(innerclasses)。 内部类可以使用public、default、protected 、private以及static修饰。而外部顶级(我们以前接触的)只能使用public和default修饰...
  • 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
  • 一、因为在创建匿名内部类的时候,会立即创建它的实例,可知匿名内部类不能是抽象,所以其必须继承一个抽象或者实现一个接口。 二、匿名内部类没有类名,因此没有构造方法。 三、匿名内部类访问的外部成员变量...
  • 就来说一说这个匿名内部类,用Java做例子,后面插一点c#。这个东西我之前也知道了很久,一直没有认真去看过,这次就来看看吧,今天的代码量相对很多。 匿名内部类 这里就说匿名内部类,关于其他内部老规矩,以后...
  •  之前介绍了Lambda表达式是匿名内部类的一种简化,因此它可以部分取代匿名内部类的作用。 相同点   * Lambda表达式与匿名内部类一样,都可以直接访问"effectively final"的局部变量,以及外部的成员变量。   *...
  • 外部内部类 众所周知,每个java文件必须有一个与这个java文件同名的外部,这个外部可以是public或default的。而除了这个同名外部,还可以有与这个同名外部平级的其他外部,但它们必须是default的。 而...
  • 简单说就是在一个内部又定义了一个,这个定义在已知类内部就称为&amp;quot;内部类”。由于是定义在一个已知内部,所以它既具备一个累的特征,又在很多方面的表现和普通有不同。 下面,我打算从...
  • [java] 匿名内部类

    2015-08-12 10:46:06
    java中的匿名内部类:  匿名内部类也就是没有名字的内部  正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写  但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 ...
  • lambda和匿名内部类

    2018-08-17 14:49:06
    在jdk8里面新加了一个lambda,其优点很多,主要是节约了代码,增加了可读性,它在很多方面和匿名内部类很相似,是高级语言的编写特征之一,结合匿名内部类讲解一下lambda的用法和特性;  注意点:  1.如果形参列表...
  • 为什么要有内部类类内部里的,称内部类内部类是为了实现多重继承。
  • Java中的匿名内部类及其使用技巧

    万次阅读 多人点赞 2017-08-08 21:59:24
    前言在介绍匿名内部类之前,首先我们应该先来了解一下内部及局部内部: 内部 内部(inner class)是定义在另一个中的,内部中的方法可以访问创建该内部(我们称其为外围 outer class)的域中...
  • 内部类也叫内置,嵌套。正文顾名思义,内部类就是一个嵌套在另一个中。内部类可以在外部的成员位置,也可以在外部的局部位置,也就是成员函数中。一般,我们在定义内部类时设置其访问权限为私有private...
  • JAVA之旅(九)——Object,equals,toString,getClass,内部访问规则,静态内部,内部原则,匿名内部类 天天被一些琐事骚扰,学习还得继续 一.Object Object是什么呢?我们可以翻阅JAVA API文档看他的...
  • 在那些修改中,引人注目的是内部类匿名类。如运用得当,它们可使程序更易理解和维护。本文介绍内部类匿名类在Java代码中是如何具体工作的,如何正确使用它们,以及如何避免一些常见的错误。 下面来看看这些特性...
  • Java在嵌套类型这里提供的特性比较多,假设:Java的字节码只支持静态嵌套内部类、局部内部类匿名局部内部类都是编译器提供的语法糖,这个假设目前没法验证(看不懂字节码),本文先来看一下C#是如何为我们提供...
  • Java中的多态、内部匿名内部类

    千次阅读 2014-06-20 22:37:26
    想要定义匿名内部类:前提是内部必须继承一个或者实现接口。 2、匿名内部类的格式:new 父类名&接口名(){ 定义子类成员或者覆盖父类方法 }.方法。 3、 匿名内部类的使用场景: 当函数的参数是接口类型...
  • 匿名内部类的特点

    千次阅读 2010-11-30 11:12:00
       在使用匿名内部类时,要记住以下几个原则:   ·匿名内部类不能有构造方法。   ·匿名内部类不能定义任何静态成员、方法和。   ·匿名内部类不能是public,protected,private,...
  • 4.10内部类 4.10.1内部类的访问规则: 1.内部类可以直接访问外部中的成员,包括私有。  之所以可以直接访问外部中的成员,是因为内部类中持有了一个外部的引用,格式外部类名.this 2.外部要访问内部类,...
  • java内部:  格式:   类名一般都是由protected和private修饰符修饰.内部很好的体现了java的封装特性.可以使用封装来解决java只能单继承的问题 . 匿名内部类: ...java的匿名内部类的语法规则看
  • java之匿名内部类中的多态

    千次阅读 2017-04-01 17:36:34
    接口,抽象匿名内部类实现多态

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 79,230
精华内容 31,692
关键字:

匿名内部类特性