问:为什么反射的性能较差?有没有什么方法可以让他变快?
参考答案: java反射要解析字节码,将内存中的对象进行解析,包括了一些动态类型,JVM难以优化,而且在调用时还需要拼接参数,执行步骤也更多。因此,反射操作的效率要更低
常用的改进性能方法主要有:
- m.setAccessible(true);
由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的;
- 用缓存将反射得到的元数据保存起来;
- 利用一些高性能的反射库,如ReflectASM ReflectASM 使用字节码生成的方式实现了更为高效的反射机制。执行时会生成一个存取类来 set/get 字段,访问方法或创建实例。一看到 ASM 就能领悟到 ReflectASM 会用字节码生成的方式,而不是依赖于 Java 本身的反射机制来实现的,所以它更快,并且避免了访问原始类型因自动装箱而产生的问题。
问:java当中的四种引用分别指什么?
参考答案:
强引用,软引用,弱引用,虚引用。不同的引用类型主要体现在GC上:
强引用,如果一个对象具有强引用,它就不会被垃圾回收器回收。即使当前内存空间不足,JVM也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象;
软引用,在使用软引用时,如果内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收,只有在内存不足时,软引用才会被垃圾回收器回收;
弱引用,具有弱引用的对象拥有的生命周期更短暂。因为当 JVM 进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象;
虚引用,顾名思义,就是形同虚设,如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收;
问:为什么要有不同的引用类型?
参考答案:
Java语言有时需要我们适当的控制对象被回收的时机,因此就诞生了不同的引用类型,可以说不同的引用类型实则是对GC回收时机不可控的妥协。比如说以下应用场景:
利用软引用和弱引用解决OOM问题:用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的空间,从而有效地避免了OOM的问题;
问:虚拟机是如何实现多态的?
参考答案:
动态绑定技术(dynamic binding),执行期间判断所引用对象的实际类型,根据实际类型调用对应的方法.
问:静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?
参考答案:
Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。而通常的内部类需要在外部类实例化后才能实例化
问:内部类的作用
参考答案:
内部类可以有多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。在单个外围类当中,可以让多个内部类以不同的方式实现同一接口,或者继承同一个类.
创建内部类对象的时刻不依赖于外部类对象的创建.内部类并没有令人疑惑的”is-a”关系,它就像是一个独立的实体。内部类提供了更好的封装,除了该外围类,其他类都不能访问
问:3*0.1==0.3返回值是什么
参考答案:
false,因为有些浮点数不能完全精确的表示出来。
问:a=a+b与a+=b有什么区别吗?
参考答案:
+=操作符会进行隐式自动类型转换,此处a+=b隐式的将加操作的结果类型强制转换为持有结果的类型,而a=a+b则不会自动进行类型转换。
举个例子,如: byte a = 23; byte b = 22; b = a + b;//编译出错 而 b += a; // 编译OK
问:int 和Integer谁占用的内存更多?
参考答案:
Integer 对象会占用更多的内存。Integer是一个对象,需要存储对象的元数据。但是int是一个原始类型的数据,所以占用的空间更少;
问:JVM、JRE、JDK及 JIT 之间有什么不同
参考答案:
java 虚拟机 (JVM),是实现java语言平台独立性的基础,可以理解伪代码字节码,提供对多个平台的良好支持,在用户和操作系统之间建立了一层枢纽。
java 运行时环境 (JRE),是JVM 的一个超集。JVM 对于一个平台或者操作系统是明确的,而 JRE 确实一个一般的概念,他代表了完整的运行时环境。在 jre 文件夹中的jar 文件和可执行文件都会变成运行时的一部分。事实上,运行时 JRE 变成了 JVM。所以对于一般情况时候使用 JRE,对于明确的操作系统来说使用 JVM。当你下载了 JRE 的时候,也就自动下载了 JVM。
java 开发工具箱 (JDK),java 开发工具箱指的是编写一个 java 应用所需要的所有 jar 文件和可执行文件。事实上,JRE 是 JDK 的一部分。如果你下载了 JDK,你会看到一个名叫 JRE 的文件夹在里面。JDK 中要被牢记的 jar 文件就是 tools.jar,它包含了用于执行 java 文档的类还有用于类签名的 jar 包。
即时编译器 (JIT),即时编译器是种特殊的编译器,它通过有效的把字节码变成机器码来提高 JVM 的效率。JIT 这种功效很特殊,因为他把检测到的相似的字节码编译成单一运行的机器码,从而节省了 CPU 的使用。这和其他的字节码编译器不同,因为他是运行时编译(从字节码到机器码)而不是在程序运行之前。正是因为这些,动态编译这个词汇才和 JIT 有那么紧密的关系。
问:Java 泛型类在什么时候确定类型?
参考答案:
在编译期间确定变量类型。类型擦除。
问:引用类型是占用几个字节?
参考答案:
hotspot在64位平台上,占8个字节,在32位平台上占4个字节。
问:JDK主流版本的差异
参考答案:
- Java 5(2004年发行),影响很大的一个版本;
- 1、泛型。
- 2、Metadata,元数据,描述数据的数据。
- 3、自动装箱和拆箱,也就是基本数据类型(如 int)和它的包装类型(如 Integer)自动帮你转换(其实背后是相关的方法帮你做了转换工作)。
- 4、枚举。
- 5、可变参数,一个函数可以传入数量不固定的参数值。
- 6、增强版的 for 循环。
- 7、改进了 Java 的内存模型,提供了 java.util.concurrent 并发包。
- Java 6(2006年发行),这个版本的 Java 更多是对之前版本功能的优化,增强了用户的可用性和修复了一些漏洞,
- 1、提供动态语言支持。
- 2、提供编译 API,即 Java 程序可以调用 Java 编译器的 API。
- 3、Swing 库的一些改进。
- 4、JVM 的优化。
- 5、微型 HTTP 服务器 API ;
- Java 7(2011年发行)
- 1、放宽 switch 的使用,可以在 switch 中使用字符串;
- 2、try-resource-with 语句,帮助自动化管理资源,如打开文件,对文件操作结束后,JVM 可以自动帮我们关闭文件资源,当然前提是你要用 try-resource-with 语句。
- 3、加入了类型推断功能,比如你之前版本使用泛型类型时这样写 ArrayList userList= new ArrayList();,这个版本只需要这样写 ArrayList userList= new ArrayList<>();,也即是后面一个尖括号内的类型,JVM 帮我们自动类型判断补全了。
- 4、简化了可变参数的使用。
- 5、支持二进制整数,在硬件开发中,二进制数更常用,方便人查看。
- 6、支持带下划线的数值,如 int a = 100000000;,0 太多不便于人阅读,这个版本支持这样写 int a = 100_000_000,这样就对数值一目了然了吧。
- 7、异常处理支持多个 catch 语句。
- 8、NIO 库的一些改进,增加多重文件的支持、文件原始数据和符号链接。
- Java 8(2014年发行)
- 1、Lambda 表达式,简化代码
- 2、注解功能的增强。重复注解和注解扩展,现在几乎可以为任何东西添加注解:局部变量、泛型类、父类与接口的实现,就连方法的异常也能添加注解。
- 3、新的时间和日期 API,在这之前 Java 的时间和日期库被投票为最难用的 API 之一,所以这个版本就改进了。
- 4、JavaFX,一种用在桌面开发领域的技术(也是和其他公司竞争,这个让我们拭目以待吧)。
- 5、静态链接 JNI 程序库(这个做安卓开发的同学应该熟悉)。
- 6、接口默认方法和静态方法
- 7、函数式接口
- 8、方法引用
- 9、java.util.stream
- 10、HashMap的底层实现有变化
- 11、JVM内存管理方面,由元空间代替了永久代。
- Java 9 (2017年发行)
- 1、模块化(这点也是向其他语言学习的,如 JavaScript)。
- 2、Java Shell(这点也是向其他语言学习的,如 Python),在这之前总有人说 Java 太麻烦,写个 Hello Word 都要新建个类,有时候测试个几行的代码都不方便,Java Shell 推出后,Java 开发者不用眼馋其他语言的 Shell 了;
- 3、即时编译功能的增强。
- 4、XML Catalogs,XML 文件自动校验。
- Java 10(2018年发行)
- 1、局部变量的类型推断 var关键字
- 2、GC改进和内存管理 并行全垃圾回收器 G1
- 3、垃圾回收器接口
- 4、线程-局部变量管控
- 5、合并 JDK 多个代码仓库到一个单独的储存库中
- Java 11(2018年发行)
- 1、本地变量类型推断
- 2、字符串加强
- 3、集合加强
- 4、Stream 加强
- Optional 加强
- 5、InputStream 加强
- 6、HTTP Client API
- 7、化繁为简,一个命令编译运行源代码