-
匿名类
2016-05-23 10:13:00匿名类(只有类体,没有类声明)分为两种,和类有关的匿名类和与接口有关的匿名类。匿名类(只有类体,没有类声明)分为两种,和类有关的匿名类和与接口有关的匿名类。
和类有关的匿名类:利用类名和类体创建一个匿名对象。此类体被认为是该类的一个子类去掉类声明后的类体,称为匿名类.
- 匿名类就是一个子类,不能用匿名类声明对象,但可以直接创建对象。
- 匿名类可以继承父类的方法也可以重写父类的方法。
- 使用匿名类时必然是在某个类中直接用匿名类创建对象,因此匿名类是一个内部类。可以访问外嵌类中的成员变量和方法,不可以声明static成员变量和方法。
- 匿名类的主要用途是向方法参数传值。
匿名类创建对象:
class A{ void f(){} } public class Examle{ public static void main(String arg[]){ A a=new A(){ void f(){print("C");} } a.f();//此时输出的结果是C。new A(){void f(){print("C");}就是匿名类,由类名和类体组成。类名和父类名相同,类体是对父类方法的重写。该匿名类相当于A的子类,省略了声明对象的功能。等价于声明一个继承了类A的子类B,然后用B创建的对象作为a的上转型对象,匿名类将这些过程简化了。 } } }
匿名类作为方法参数:
class A{ void getval(int n){print ("0");} } class B{ void f(A a){a.getval(3);} } main(){ B b=new B(); b.f(new A(){void getval(int n){print(n*n);}})//匿名类创建的对象作为参数,将该对象的引用船队给方法f的参数a。 }
new A(){void getval(int n){print(n*n);}} (匿名类)等价于创建了一个A的子类,重写了f()方法,然后将该对象作为参数传递给对象a,使其转为上转型对象,这样可以调用匿名类重写的方法。
和接口有关的匿名类:
使用接口和类体创建一个匿名对象。此类体被认为是实现了接口的类去掉类声明的类体,称为匿名类。
如果某个方法的参数是接口类型,那么可以使用接口名和类体组合的方式创建一个匿名对象,传递给方法的参数,类体必须要实现接口中的所有方法。interface Com{ getval(int n); } void f(Com x){ x.getval(2); } f(new Com(){getval(int n)print(n*n);})//使用匿名类创建对象,将该对象传递给方法f的参数Com 当然也可以使用匿名类创建对象,接口变量存放该对象的引用,可回调实现该接口类中的方法。 Com com=new Com(){getval(int n)print(n*n);} com.getval(4);
-
Java 匿名类(匿名内部类)
2020-12-25 23:41:48Java匿名类(匿名内部类) 学习的参考博文:无恨之都 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
接口的地方局部类的格式是:
- 创建局部类并且实现接口:
class EnglishGreeting implements HelloWorld {...}
- 创建局部类的实例化对象并用接口类型接收:
HelloWorld englishGreeting = new EnglishGreeting();
- 调用实例化对象的方法
匿名类的格式是:
- 创建匿名类实现接口同时对其进行实例化:
HelloWorld frenchGreeting = new HelloWorld() {...}
- 调用实例化对象的方法
【区别】
- 局部类
EnglishGreeting
实现HelloWorld
接口,有自己的类名:EnglishGreeting
,定义完成后需要再对其实例化对象:englishGreeting
才能可以使用方法 - 匿名类在定义时就已经实例化成对象:
frenchGreeting
,定义完了就可以直接使用方法 - 匿名类是一个表达式,因此在定义的最后用分号结束
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(); }
【结果】
杰瑞
【分析】
main
方法创建匿名类实现TomInterface
接口并实例化:new TomInterface{...}
- 调用匿名类对象的
setName
方法,将杰瑞
赋值给匿名类的成员变量name
,并返回当前实例this
给接口变量tif
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方法=张三 匿名类 - 李四
【分析】
- 创建父类对象并调用
getName
方法,这个不用细说 - 创建匿名类继承父类并实例化对象:
pc
,本次匿名类调用的是父类的带参构造,将参数赋值给了父类的name
- 调用匿名类重写的
getName
方法,得到新的name
值
3.3 区别
Demo demo = new Demo(xxx){...}
- 操作符:new
- 一个要实现的接口或要继承的类,示例3.1 是实现接口,示例3.2 是继承类
- 一对括号,如果是匿名子类,那么父类有构造参数就填,不带参就空着;如果匿名类是实现接口,那么括号里需要空着
{...}
,括号里括着的是匿名类的声明主体- 末尾的
;
号,因为匿名类的声明是一个表达式,是语句的一部分,所以需要分号结尾 - 表面上看匿名类没有类名,没有构造参数。但其实在编译的时候,编译器会给匿名类分配类名和构造器,只是我们无法操作也不能复用。如需验证,可以看编译后的class文件,多出一个命名格式:
匿名类定义类$?.class
的文件。例如示例3.2,匿名类的class文件就是:ExtendTest$1.class
-
1.18 Java匿名类,匿名内部类
2020-09-30 13:12:36匿名类是指没有类名的内部类,必须在创建时使用 new 语句来声明类。其语法形式如下: new <类或接口>() { // 类的主体 }; 这种形式的 new 语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个...匿名类是指没有类名的内部类,必须在创建时使用 new 语句来声明类
。其语法形式如下:new <类或接口>() { // 类的主体 };
这种形式的 new 语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个给定的接口。使用匿名类可使代码更加简洁、紧凑,模块化程度更高。
匿名类有两种实现方式:
- 继承一个类,重写其方法。
- 实现一个接口(可以是多个),实现其方法。
下面通过代码来说明。
public class Out { void show() { System.out.println("调用 Out 类的 show() 方法"); } } public class TestAnonymousInterClass { // 在这个方法中构造一个匿名内部类 private void show() { Out anonyInter = new Out() { // 获取匿名内部类的实例 void show() { System.out.println("调用匿名类中的 show() 方法"); } }; anonyInter.show(); } public static void main(String[] args) { TestAnonymousInterClass test = new TestAnonymousInterClass(); test.show(); } }
程序的输出结果如下:
调用匿名类中的 show() 方法
从输出结果可以看出,匿名内部类有自己的实现。
提示:匿名内部类实现一个接口的方式与实现一个类的方式相同,这里不再赘述。
例2:
最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口
在这里我们看到使用匿名内部类我们必须要继承一个父类或者实现一个接口,当然也仅能只继承一个父类或者实现一个接口。同时它也是没有class关键字,这是因为匿名内部类是直接使用new来生成一个对象的引用。当然这个引用是隐式的。abstract class Bird{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public abstract int fly(); } public class Test { public void test(Bird bird){ System.out.println(bird.getName()+"能够飞"+bird.fly()+"米"); } public static void main(String[] args) { Test test=new Test(); test.test(new Bird(){ @Override public int fly() { return 10; } public String getName(){ return "无翼鸟"; } }); } }
无翼鸟能够飞10米
在Test类中,test()方法接受一个Bird类型的参数,同时我们知道一个抽象类是没有办法直接new的,我们必须要先有实现类才能new出来它的实现类实例。所以在mian方法中直接使用匿名内部类来创建一个Bird实例。
由于匿名内部类不能是抽象类,所以它必须要实现它的抽象父类或者接口里面所有的抽象方法。匿名类有如下特点:
1)匿名类和局部内部类一样,可以访问外部类的所有成员。如果匿名类位于一个方法中,则匿名类只能访问方法中 final 类型的局部变量和参数。
public static void main(String[] args) { int a = 10; final int b = 10; Out anonyInter = new Out() { void show() { // System.out.println("调用了匿名类的 show() 方法"+a); // 编译出错 System.out.println("调用了匿名类的 show() 方法"+b); // 编译通过 } }; anonyInter.show(); }
从 Java 8 开始添加了 Effectively final 功能,在 Java 8 及以后的版本中代码第 6 行不会出现编译错误,
2)匿名类中允许使用非静态代码块进行成员初始化操作。
Out anonyInter = new Out() { int i; { // 非静态代码块 i = 10; //成员初始化 } public void show() { System.out.println("调用了匿名类的 show() 方法"+i); } };
3)匿名类的非静态代码块会在父类的构造方法之后被执行。
注意事项
在使用匿名内部类的过程中,我们需要注意如下几点:
1、使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
2、匿名内部类中是不能定义构造函数的。
3、匿名内部类中不能存在任何的静态成员变量和静态方法。
4、匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
5、匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
-
匿名类、内部类、匿名内部类
2019-01-04 10:49:02前端时间在写.net项目中,一直错将.cs里的两个class当作内部类,原来是一个文件里的两个类而已,这让我想起了Java中的内部类,比较内部类,那么还有两个类,那就是匿名类和匿名内部类。今天我想就Java中的这三种类...前端时间在写.net项目中,一直错将.cs里的两个class当作内部类,原来是一个文件里的两个类而已,这让我想起了Java中的内部类,比较内部类,那么还有两个类,那就是匿名类和匿名内部类。今天我想就Java中的这三种类进行个比较。
我们知道在Java语言规范中可以做很多事,例如一个类或一个接口中可以声明一个类或接口,在一个方法中可以声明一个类,类与接口声明可以嵌套任意深度等。
匿名类:
1、new <类或接口><类的主体>,匿名类的声明是在编译时进行的,实例化是在运行时进行的,所以在for循环中一个new语句会创建相同匿名类的几个实例,而不是创建几个不同匿名类的一个实例。
2、如果要执行的对象需要一个对象,但却不值得创建全新的对象(可能是因为该对象只在一个方法内部使用),在这个时候使用匿名类就会非常合适,所以说,匿名类一般会在swing程序中快速创建事件处理程序。
- firstButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- getTxtValue().setText("第一个按钮触发的事件!");
- }
- });
3、从技术上说,匿名类可以被看作非静态的内部类,所以他们具有方法内部声明的非静态内部类相同的权限和限制。
内部类:
内部类顾名思义就是在一个类的内部还有一个类
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:xdwangiflytek@gmail.com
- */
- public class InnerClassDemo {
- public static void main(String[] args) {
- new Outer().fun();
- }
- }
- class Outer {
- private String name = "Hello 内部类";
- class Inner {
- public void print() {
- System.out.println("name = " + name);
- }
- };
- public void fun() {
- new Inner().print();
- }
- }
内部类生成的.class文件名为:Outer$Inner.class,从上面的结构发现内部类的的缺点是“结构非常的混乱”。
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:xdwangiflytek@gmail.com
- */
- public class InnerClassDemo02 {
- public static void main(String[] args) {
- new Outer02().fun();
- }
- }
- class Outer02 {
- private String name = "Hello 内部类";
- public void fun() {
- new Inner02(this).print();
- }
- public String getName() {
- return this.name;
- }
- };
- class Inner02 {
- private Outer02 out;
- public Inner02(Outer02 out) {
- this.out = out;
- }
- public void print() {
- System.out.println("name = " + this.out.getName());
- }
- };
从上可以看出内部类的优点是“可以方便的访问外部类中的私有成员”;
如果要在外部直接使用内部类的实例化对象:
外部类.内部类 内部类对象 = 外部类实例.new 内部类实例();
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:xdwangiflytek@gmail.com
- */
- public class InnerClassDemo03 {
- public static void main(String[] args) {
- Outer03 out = new Outer03();//外部类实例
- Outer03.Inner inner = out.new Inner();//实例化内部类对象
- inner.print();
- }
- }
- class Outer03{
- private String name = "Hello 内部类";
- class Inner {
- public void print() {
- System.out.println("name = " + name);
- }
- }
- }
一个内部类如果使用static关键字声明的话,则此内部类就将成为外部类,可以直接通过外部类.内部类的形式访问
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:xdwangiflytek@gmail.com
- */
- public class InnerClassDemo04 {
- public static void main(String[] args) {
- Outer04.Inner inner = new Outer04.Inner();// 实例化内部类对象
- inner.print();
- }
- }
- class Outer04 {
- private static String name = "Hello 内部类";
- static class Inner {
- public void print() {
- System.out.println("name = " + name);
- }
- }
- }
内部类可以在任意的地方使用,例如方法中声明
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:xdwangiflytek@gmail.com
- */
- public class InnerClassDemo05 {
- public static void main(String[] args) {
- new Outer05().fun();
- }
- }
- class Outer05 {
- private static String name = "Hello 内部类";
- public void fun() {
- class Inner {
- public void print() {
- System.out.println("name = " + name);
- }
- }
- new Inner().print();
- }
- }
在方法中定义的内部类,可以直接访问外部类中的各个成员,但是如果要访问方法中的参数,则需要在参数上加上final关键字声明;
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:xdwangiflytek@gmail.com
- */
- public class InnerClassDemo06 {
- public static void main(String[] args) {
- new Outer06().fun(20);
- }
- }
- class Outer06 {
- private static String name = "Hello 内部类";
- public void fun(final int temp) {
- class Inner {
- public void print() {
- System.out.println("temp = " + temp);
- System.out.println("name = " + name);
- }
- }
- new Inner().print();
- }
- }
匿名类与内部的联系与区别:
按所在位置可以分为两大类:
1、在类的方法中
特点:
a、可以访问宿主类的所有元素 ;
b、保存宿主类对象的引用,创建对象时必须有宿主类对象;
c、 不能有静态数据;
继续划分:
A、本地内部类;
B、匿名内部类
两者的区别在于本地内部类有构造方法,而匿名内部类只能实例初始化;
2、在类或接口作用域中;
继续划分:
A、普通内部类
B、静态内部类
匿名内部类:
匿名内部类是在抽象类和接口的基础之上发展起来的。
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:xdwangiflytek@gmail.com
- */
- public class NoNameClass01 {
- public static void main(String[] args) {
- new X().fun2();
- }
- }
- interface A {
- public void fun();
- }
- class B implements A {
- public void fun() {
- System.out.println("Hello 准备匿名内部类");
- }
- }
- class X {
- public void fun1(A a) {
- a.fun();
- }
- public void fun2() {
- this.fun1(new B());
- }
- }
通过上面的Demo,如果现在假设B类只使用一次,那么还有必要将其定义成一个单独的类么?
呵呵,此时就可以使用匿名内部类:
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:xdwangiflytek@gmail.com
- */
- public class NoNameClass02 {
- public static void main(String[] args) {
- new XX().fun2();
- }
- }
- interface AA {
- public void fun();
- }
- class XX {
- public void fun1(AA a) {
- a.fun();
- }
- public void fun2() {
- this.fun1(new AA() {
- public void fun() {
- System.out.println("Hello 准备匿名内部类");
- }
- });
- }
- }
其实在真正的项目开发中匿名内部类使用的非常之少,一般在Java的图形界面和现在的Android中使用的比较多点。
最后给一个内部类实现的简单链表:
- package com.iflytek.innerclass;
- /**
- * @author xudongwang 2012-1-11
- *
- * Email:xdwangiflytek@gmail.com
- */
- public class LinkDemo {
- public static void main(String args[]) {
- Link link = new Link();
- link.add("A");
- link.add("B");
- link.add("C");
- link.add("D");
- link.add("E");
- link.print();
- }
- };
- class Link {
- class Node {
- private String name;
- private Node next; // 单向链表,每个节点指向下一个节点
- public Node(String name) {
- this.name = name; // 通过构造方法为name属性赋值
- }
- public void addNode(Node newNode) { // 增加节点
- if (this.next == null) {
- this.next = newNode; // 保存节点
- } else {
- this.next.addNode(newNode); // 继续向下查找
- }
- }
- public void printNode() { // 输出节点
- System.out.println(this.name);
- if (this.next != null) { // 此节点之后还存在其他的节点
- this.next.printNode();
- }
- }
- };
- private Node root; // 链表的头
- public void add(String name) { // 增加节点
- Node newNode = new Node(name); // 定义一个新的节点
- /*
- * 如果是第一个节点,则肯定是根节点, 如果是第二个节点,则肯定放在根节点next中 如果是第三个节点,则肯定放在第二个节点的next中
- */
- if (this.root == null) {
- this.root = newNode; // 将第一个节点设置成根节点
- } else {
- // 肯定要放在最后一个节点之后
- // 通过节点.next来不断的判断
- this.root.addNode(newNode);
- }
- }
- public void print() {
- if (this.root != null) { // 如果根节点为空了,则没有任何内容
- this.root.printNode();
- }
- }
- };
-
内部匿名类和匿名类
2013-10-17 23:52:10内部匿名类必须是继承了抽象类或者实现了借口的类 匿名类就是没有名字的类,比如new Person(); -
匿名类和匿名对象
2018-06-20 17:25:40匿名类匿名类(也叫匿名内部类)他是内部类的一种匿名类在类中只能使用一次,它通常用来简化代码的编写,但使用匿名类还有一个前提条件:它必须继承一个父类或者一个接口,因此这个匿名类会被默认为这个父类或者接口... -
Java 匿名类
2019-08-09 10:47:391、匿名类 匿名类,就是没有名称的类,其名称由Java编译器给出,一般是形如:外部类名称+$+匿名类顺序,没有名称也就是其他地方就不能引用,不能实例化,只用一次,当然也就不能有构造器。 匿名类根据位于地方... -
6.2 匿名类
2019-07-20 17:22:11和类有关的匿名类 和接口有关的匿名类 一:和类有关的匿名类 Java允许用户直接使用一个类的子类的类体创建一个子类对象 在创建子类对象时,除了使用父类的构造方法外还有类体,此类体被认为是一个子类去掉类声明... -
7.2 匿名类
2017-11-30 17:33:237.2 匿名类 7.2.1 和子类有关的匿名类 //匿名类创建对象,Bank是类 new Bank(){ 匿名类类体 };匿名类特点: (1)可以继承父类方法,也可以重写父类方法 (2)使用匿名类的时候,必然是在某个类中直接使用匿名类创建... -
匿名类,内部类,匿名内部类
2016-10-09 19:50:12今天偶然被看到匿名类,于是想起了匿名内部类,进而又想起了内部类,搜索了下他们的关系,如果描述有误,请指正。内部类java内部类分为: 成员内部类、静态嵌套类、方法内部类、匿名内部类 。1、成员内部类class ... -
PHP匿名类
2018-10-17 23:56:14PHP匿名类 -
匿名类对象
2019-09-03 15:48:12匿名类对象:创建类的对象是匿名的。 1)当我们只需要一次调用类的对象的时候,我们可以考虑使用匿名的方式创建类的对象。 2)特点:创建的匿名类的对象只能够调用一次。 ... -
关于匿名类
2018-10-24 22:43:50首先匿名类肯定是内部类。JAVA内部类分为成员内部类和局部内部类。成员内部类和成员变量类似,定义在方法外面,而局部内部类则和局部变量类似,定义在方法里面。匿名类属于局部内部类。 匿名类的应用场景一般是实现...