背景:

最近有同事跟我说了他面试时遇到的问题,考官问:“接口和抽象类可以被new嘛?”。这可能不是考官的原话,但是据他表达考官大概就是这个意思了。听到这个问题,我的第一反应是肯定不行啊,直接对接口和抽象类调用new,编译器都过不去。但是他说,考官说可以,用匿名内部类实现。听见这个回到,我感觉那个考官太………,有点无语。我们可以仔细分析下这个问题。

直接new接口和抽象类

首先先明确一点,直接new接口和抽象类,这肯定行不通,编译器会提示Cannot instantiate the type XX的错误。这个实验就不做了,没意思。

使用匿名内部类

下面的代码是一个匿名内部类的Demo,也就是考官说的可以new。

 1 package com.saillen.test;
 2
 3 interface A {
 4     void f();
 5 }
 6
 7 public class T {
 8
 9     public T(A a) {
10         a.f();
11     }
12
13     public static void main(String[] args) {
14         T t = new T(new A() {
15             public void f() {
16                 System.out.println("我是匿名内部类");
17                 System.out.println("Class对象是:" + this.getClass());
18                 System.out.println("类名字是:" + this.getClass().getSimpleName());
19             }
20         });
21     }
22
23 }

上面的程序很简单,我们使用匿名内部类,然后“new”一个接口A的对象,输出它的类名了Class对象,输出如下:

1 我是匿名内部类
2 Class对象是:class com.saillen.test.T$1
3 类名字是:

通过输出可以看到,内部类的类名是“”也就是一个空字符串,但是它确确实实是有类型的。而且查看编译后的class文件,会发现,会多一个T$1.class,这个class就是匿名内部类的原型,

用javap反编译这个文件,可以看到这个类的源码样式如下:

通过反编译后的文件可以证明,我们的“匿名内部类”的类名是Test$1。所以new针对的还是普通的class(虽然内部类和普通类有很大不一样),只不过这个class的写法稍有不同,它是编译器帮我们从匿名内部类中提取的。

结论:

通过上面的实验,我仍然坚持,接口和抽象类不可以被new!匿名内部类只是一种写法上的迷惑而已。这个考官的答案很不靠谱,不能说他的想法就是绝对的错,但是绝对不应该这么问这个问题,这不是一个能不能就回答的。或者说不能从字面上就证明可以对interface或者abstract class使用new。

内部类总结

Java编程思想第十章专门介绍了内部类,内部类确实神奇而且复杂。但是内部类在编程中被应用的场景很少,这主要是看设计者的设计思想,不过它的语法和特性却有很多。对于内部类来说要记住可以继承内部类但是不能覆盖

普通内部类:

普通的内部类,就是在class里面普通的定义一个类,eg:

1 public class A{
2     public class B{
3
4     }
5
6 }

普通内部类,或者说平凡的内部类,有如下特性:(总结自《Java编程思想》)
   (1)这个类在外部类的外面不能被直接访问,需要通过OuterClassName.InnerClassName方式访问。比如Map的Map.Entry就是一个内部接口,只能通过Map.Entry方式来使用它。

(2)内部类对象在创建后会秘密的链接到外部类对象上,隐含的有一个指向外部类对象的引用,所以没有外部类对象,是无法实例化内部类对象的。也就是我们无法独立于外部类创建一个内部类对象。(这里不包括声明为static的内部类,那不是平凡的内部类

(3)因为内部类隐含的有一个指向外部类的指针,所以内部类可以访问外围类的成员,而且是外围类的所有成员,包括private的成员。

(4)在内部类中使用OuterClassName.this可以访问外围类对象。

(4)如果想要在外部类外面实例化内部类对象,那么可以同.new语法,也就是outerObject.new InnerClass()的方式,eg:

 1 package com.saillen.test;
 2
 3 public class A {
 4
 5     public void f() {
 6         A.B b = this.new B();
 7         B b2 = new B();
 8     }
 9
10     public class B {
11              void g(){
12                 System.out.println(A.this);
13              }
14     }
15
16     public static void main(String[] args) {
17         A a = new A();
18         A.B b = a.new B();
19     }
20
21 }

(5)内部类最大的用途是:它可以实现接口或者继承某个类,这样使用内部类时,用基类引用内部类对象,可以屏蔽内部类的细节。这样的好处是,可以实现伪“多重继承”等。

(6)普通的内部类不能有static字段和static数据,也不能包含嵌套类。

在方法和作用域内的内部类:

如果内部类出现在了方法和作用域内,那么它就不是“平凡”的内部类了,而且这个内部类的作用域就是在这个方法的作用域内,方法外面是无法访问到的!但是它仍然具有“平凡”的内部类特性。

匿名内部类:

匿名内部类,在内部类的基础上减少了对class的定义,直接用new 后面跟一个接口或者基类,然后类体里面实现方法即可,这样JVM会调用编译器生成的构造器来生成这个内部类对象,并且编译器帮忙生成这个内部类的类结构。匿名内部类好处是语法简单,但是不方便阅读,在Android编程中,对Button的监听经常会用匿名内部类。匿名内部类有一些限制:匿名内部既可以扩展类,也可以实现接口,但是不能两者兼备,而且只能实现一个接口。

嵌套类:

嵌套类就是在内部类的基础上加上static声明,也就是静态的内部类。嵌套类跟普通的内部类特性有很大不同,特点:

(1)在构造时,不需要外围类的对象,但是同样,它只能访问外围类中的static字段;

(2)嵌套类可以有static数据和字段;

(3)嵌套类可以作为接口的一部分,这样在接口中就可以用公用代码出现;

(4)嵌套类是可以多重嵌套的,嵌套多少层不重要,它都可以访问它所有外围类成员。

内部类标识符:

部类必须生成一个class文件以包含它的Class对象信息,这些类文件有严格的命名规则:外围类的名字,加上“$”,再加上内部类的名字。

为什么需要内部类:

《Java编程思想》中很明确指出:

 每个内部类都能独立的继承自一个(接口的)实现,所以无论外围类是否已经继承了某个实现,对于内部类都没有影响。

利用内部类可以实现多重继承等好处,使用内部类还可以实现java版的闭包和回调,而且比指针更灵活、更安全。

转载于:https://www.cnblogs.com/sunpengblog/p/10474739.html

Java 接口和抽象类可以被new么?相关推荐

  1. java接口和抽象类的区别(经典面试题)

    java接口和抽象类的区别(经典面试题) 要了解接口和抽象类的区别,首先需要明白接口和抽象类的定义. 1.抽象类 包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可 ...

  2. 什么时候使用接口?什么时候使用抽象?选择Java接口还是抽象类 (转)

    老帖了,但是还是想自己收录一下.最后也把自己对于这个问题的一些粗糙的理解记录下来. 在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的.在这种情况下,各个对象内部是如何实现自己的对 ...

  3. java接口和抽象类的区别和作用

    java接口和抽象类的区别和作用 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过(implements)接口的方 ...

  4. 选择Java接口还是抽象类

    很多人有过这样的疑问:为什么有的地方必须使用接口而不是抽象类,而在另一些地方,又必须使用抽象类而不是接口呢?或者说,在考虑Java类的一般化问题时,很多人会在接口和抽象类之间犹豫不决,甚至随便选择一种 ...

  5. java 接口与抽象类的区别

    1.概述 一个软件设计的好坏,我想很大程度上取决于它的整体架构,而这个整体架构其实就是你对整个宏观商业业务的抽象框架,当代表业务逻辑的高层抽象层结构 合理时,你底层的具体实现需要考虑的就仅仅是一些算法 ...

  6. Java 接口和抽象类可以被new么?——顺便总结内部类

    转载:https://blog.csdn.net/hackersaillen/article/details/47281549 背景: 最近有同事跟我说了他面试时遇到的问题,考官问:"接口和 ...

  7. java 接口和抽象类的区别6_JAVA基础篇-接口和抽象类的区别

    .前言 JAVA是一种面向对象语言,具备抽象(Abstract),封装(packing),继承(extends),多态(polymorphic)四大特性. 我们重点从oop思想∠来分析. .在面向对象 ...

  8. 抽象类中不能有private的成员_【java基础】-- java接口和抽象类的异同分析

    在java中,通常初学者搞不懂接口与抽象类,这也是面试比较容易问到的一个问题.下面我来谈谈自己的理解.如有不妥之处,还望批评指正,不胜感激. 1.抽象类怎么定义和继承? 2.接口怎么定义和实现? 3. ...

  9. 通过实例讲解java接口和抽象类的特殊实现方法

    一.java中的接口本质上是加约束的抽象类 //抽象类 public abstract class AExample { public abstract int add(int x,int y): p ...

最新文章

  1. ATP - UI 自动化测试用例管理平台搭建
  2. 5月14日 游戏闯关,
  3. Leetcode 之Count and Say(35)
  4. K8S的 Custom Resource Definition(CRD)之初体验
  5. linux dns配置bind9,DNS服务(bind9)配置过程
  6. System memory 466092032 must be at least
  7. 值类型和引用类型的区别
  8. Kaggle新赛:自动检测赛场上的头盔撞击事件
  9. iptables官方文档
  10. Linux下用多种模式实现双网卡绑定!
  11. 强大新UI装逼神器微信小程序源码+多模板支持多种流量主模式
  12. 【软件工程】第一章 软件工程概述 考试重点 复习记录
  13. 向量与直线,梯度与法向量,切向量
  14. 货物列车尾部安全防护装置
  15. [Python数据分析]NBA的球星们喜欢在哪个位置出手
  16. docker — 容器镜像
  17. 【IKAnalyzer中文分词器详解-(1)分词逻辑】
  18. 服务器虚拟机6的安装教程,VMware vCenter 6.7 安装过程(图文教程)
  19. Asp.net Core 6.0 使用EF DB First 连接mysql
  20. (一)Redis——五大数据类型及基础知识

热门文章

  1. 1024“代码急救室”活动来袭!机械键盘、背包等程序员装备等你来!
  2. mPaaS 月度小报 | 3月发生的大事件
  3. OpenAI 挑战《索尼克》,阿里南大队如何一举夺魁?
  4. 棱镜调查:提高渠道兼容性从游戏设计开始
  5. Postman(使用指南)
  6. 解决远程登陆Linux误按ctrl+s锁屏
  7. goldengate for oracle 10g学习
  8. llinux的shell脚本编程详解
  9. linux 远程控制详细安装 -- VNC (转)
  10. 在IDEA中使用MyBatis Generator逆向工程生成代码