面试1-Java基础

1.你常用的jdk类有哪些,说出5个?

答:String,StringBuffer,StringBuilder,Integer,ArrayList,HashMap,Date

2.请你说说String、StringBuiler、Stringbuffer的区别?

答:第一,可变性方面,String是不可变的,StringBuiler和StringBuffer是可变的,因为String只用只读字符数组保存字符串,private final char value[],所以是不可变的,jdk9将char改成了byte,占用更少的空间。而StringBuiler和StringBuffer都继承自AbstractStringBuiler类,在AbstractStringBuiler类中也是使用字符数组保存字符串的 char[] value,这两种对象都可变。

第二,线程安全性,String 和 StringBuffer 是线程安全的,StringBuiler是线程不安全的。String的线程安全是因为其对象是不可变的,StringBuffer线程安全是因为对方法加了同步锁或者对调用的方法加了同步锁。StringBuiler并没有对方法加同步锁,所以是线程不安全的。

第三,性能,String的性能较差,因为每次对String类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String对象。而StringBuiler/StringBuffer的性能更高,是因为每次都是对对象本身的操作,而不是生成新的对象并 改变对象的引用,一般情况下,StringBuiler比StringBuffer可获得10%-15%左右的性能提高。

总结来说,如果操作量少的数据用String,单线程操作字符串缓冲区下操作大量数据使用StringBuiler,多线程操作字符串缓冲区下操作大量数据用StringBuffer。

3.两个对象值相同 (x.equals (y) == true) ,但却可有不同的 hash code,这样说对不对?

答:不对,如果两个对象x,y满足x.equals(y) == true,他们的hashcode应该相同。Java对于equals和hashcode方法的规定是这样的:(1)如果两个对象相同(equals返回true)那么他们的hashcode一定要相同。如果两个对象的hashcode相同,他们并不一定相同。equals要满足,自反性,对称性,传递性,一致性;

4.String 类型为什么设计成 final 且不可变的?

5.如果你的 Serializable 类中包含一个不可序列化的成员,会发生什么?如何解决呢

答:任何序列化该类的尝试都会因 NotSerializableException 而失败,但这可以通过在 Java 中给属性设置瞬态 (transient) 变量来轻松解决 。

6. Java 有没有 goto? 如果有,一般用在什么地方?如果没有,如何跳出当前的多重嵌套循环?

答:goto 是 Java 中的保留字,在目前版本的 Java 中没有使用。

Java 中跳出多重循环有三种方式:

       1)break + 标签:在最外层循环前加一个标签如 label,然后在最里层的循环使用用 break label;

       2)通过捕获异常

       3)通过标置变量

7.final、finally、finalize的区别是什么

答:final用于声明属性、方法和类,分别表示属性不可变、方法不可覆盖重写、类不能被继承;finally是异常处理语句结构的一部分,表示总被执行;

finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件。

8.final有哪些用法

答:

被final修饰的类不可以被继承

被final修饰的方法不可以被重写

被final修饰的变量不可以被改变.如果修饰引用,那么表示引用不可变,引用指向的内容可变.

被final修饰的方法,JVM会尝试将其内联,以提高运行效率

被final修饰的常量,在编译阶段会存入常量池中.

9.关键字 switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上?

答:在Java 5以前,switch(expr)中,expr只能是byte、short、char、int。从Java 5开始,Java中引入了枚举类型,expr也可以是enum类型,

从Java 7开始,expr还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。

10.抽象类(abstract class )和接口(interface )有什么异同?

答:相同点:①都不能直接实例化,如果要实例化,抽象类变量必须实现所有抽象方法,接口变量必须实现所有接口为实现的方法;

       ②都可以有实现方法(Java8之前接口不能有实现方法)

     ③都可以不需要实现类或者继承者去实现所有方法(java8以前的接口,java8以后的接口中可以包括默认方法,不需要实现者实现);

不同点: ①抽象类和接口所反映的涉及理念不同,抽象类表示的是对象/类的抽象,接口表示对行为的抽象。

       ②抽象类不可以多重继承,接口可以多重继承,即一个类只能继承一个抽象类,却可以继承多个接口。

       ③抽象类中的方法可以用public protected和default abstract修饰符,不能用private static synchronize native修饰,变量可以在子类中重新定义,也可以重新赋值

       接口的方法默认修饰符是 public abstract,java8开始出现静态方法多加static关键字,默认变量是public static final型,且必须给初值,在实现类中不能重新定义,也不能改变其值。

       ④抽象类可以有构造器,接口没有构造器。

11.Java 创建对象的方式有哪些?

答:1)使用new关键字;

       2)反射,使用Java.lang.Class类的newinstance方法;

              //方式一,使用全路径包名

              User user = (User)Class.forName("com.imooc.interview.demo.User").newInstance();

              //方法二,使用 class 类

              User user = User.class.newInstance();

       3)反射,使用 java.lang.reflect.Constructor 类的 newInstance 方法

              Constructor<User> constructor = User.class.getConstructor();

              User user = constructor.newInstance();

       4)使用 clone 方法。

              User person = new User(new Integer(200));

              User clone = person.clone();

              浅拷贝:被复制对象的所有变量都含有与原来对象相同的值,对拷贝后对象的引用仍然指向原来的对象。

              深拷贝:不仅要复制对象的所有非引用成员变量值,还要为引用类型的成员变量创建新的实例,并且初始化为形式参数实例值。

              要注意的是,clone () 是 Object 的 native 方法,但如果要标注某个类是可以调用 clone (),该类需要实现空接口 Cloneable。

       5)使用反序列化。

              为了序列化 / 反序列化一个对象,需要该类实现空接口 Serializable。序列化时首先创建一个输出流对象 oos, 使用 oos 的 writeObject () 方法将 p对象写入 oos 对象中去。使用反序列化创建对象时,首先创建一个输入流对象ois,使用输入流对象 ois 的 readObject () 方法将序列化存入的对象读出,重新创建一个对象。序列化是深拷贝

12.java.lang.Class 类的 newInstance 方法和 java.lang.reflect.Constructor 类的newInstance 方法有什么区别?

答:①Class的newinstance只能触发无参数构造方法创建对象,而构造器类的newinstance能触发有参数或者任意参数的的构造器方法来创建对象。

       ②Class的newinstance需要其构造方法是public的或者对调用方可见的,而构造器类的newinstance可以在特定环境下调用私有构造方法来创建对象。

       ③Class的newinstance抛出类构造函数的异常,而构造器类的newinstance包装了一个InvocationTargetException异常。

说明:Class类本质上调用了反射包Constructor中无参数的newInstance方法,捕获了InvocationTargetException,将构造器本身的异常抛出

13.static都有哪些用法?

答:

       静态变量

       静态方法

       静态块,多用于初始化

       静态内部类.

       静态导向,即import static.import static是在JDK 1.5之后引入的新特性,可以用来指定导入某个类中的静态资源,并且不需要使用类名.资源名,可以直接使用资源名,

       比如:

       import static java.lang.Math.sin;

       public class Test{

       public static void main(String[] args){

              //System.out.println(Math.sin(20));传统做法

              System.out.println(sin(20)); // 静态导包

              }

       }

14. java 中继承类用 extends,继承接口用关键字 implements。都是继承,为什么要用两个关键字呢?

15.列出一些你常见的运行时异常?

答:ArithmeticException(算术异常)、   ClassCastException (类转换异常)、IllegalArgumentException (非法参数异常)、IndexOutOfBoundsException (下标越界异常)、NullPointerException (空指针异常)、SecurityException (安全异常)

16.error和exception有什么区别?运行时异常与受检异常有何异同?

答:error通常表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出、不可能指望程序能处理这样的情况;exception通常表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况;

运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生;受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。

Java编译器要求方法必须声明抛出可能发生的受检异常,但是并不要求必须声明抛出未被捕获的运行时异常。

17.String对象的intern()是指什么?

答:intern()方法会首先从常量池中查找是否存在该常量值,如果常量池中不存在则现在常量池中创建,如果已经存在则直接返回. 比如 String s1="aa"; String s2=s1.intern(); System.out.print(s1==s2);//返回true

18.抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?为什么?

答:都不能。

抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的;

本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的;

synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的;

19.面向对象的特征有哪些?

答:

  • 抽象:

  抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。

  • 继承:

  继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。

  • 封装:

  封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。

  • 多态性:

  多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。

20.代码中如何实现多态?

答:实现多态主要有以下三种方式:

       接口实现

       继承父类重写方法

       同一类中进行方法重载

21.overload和overide的区别?

答:第一,Override 可以翻译为覆盖,从字面就可以知道,它是覆盖了一个方法并且对其重写,以求达到不同的作用。对我们来说最熟悉的覆盖就是对接口方法的实现,在接口中一般只是 对方法进行了声明,

而我们在实现时,就需要实现接口声明的所有方法。除了这个典型的用法以外,我们在继承中也可能会在子类覆盖父类中的方法。

在覆盖要注意 以下的几点:

       ①覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;

       ②覆盖的方法的返回值必须和被覆盖的方法的返回值一致;

       ③覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;

       ④被覆盖的方法不能为 private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。

第二,Overload 可以翻译为重载,它是指我们可以定义一些名称相同的方法,通过定义不同的输入参数来区分这些方法,然后再调用时,VM就会根据不同的参数样式,来选择合适的方法执行。

在使用重载要注意以下的几点:

       ①. 在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是 fun(int,float),但是不能为 fun(int,int));

       ②. 不能通过访问权限、返回类型、抛出的异常进行重载;

       ③. 方法的异常类型和数目不会对重载造成影响;

       ④. 对于继承来说,如果某一方法在父类中是访问权限是 private,那么就不能在子类对其进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。

总之,重写(Override) 是父类与子类之间多态性的一种表现,重载 (Overload) 是一个类中多态性的一种表现。很重要的一点就是,Overloaded 的方法是可以改变返回值的类型。

另外:在Java语言规范中,一个方法的特征仅包括方法的名字,参数的数目和种类,而不包括方法的返回类型,参数的名字以及所抛出来的异常。在Java编译 器检查方法的重载时,

会根据这些条件判断两个方法是否是重载方法。但在Java编译器检查方法的置换时,则会进一步检查两个方法(分处超类型和子类型)的 返还类型和抛出的异常是否相同。

22.使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?

答:使用 final 关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改 变的。

例如,对于如下语句:

       final StringBuffer a=new StringBuffer("immutable");

       执行如下语句将报告编译期错误:

       a=new StringBuffer("");

       但是,执行如下语句则可以通过编译:

       a.append(" broken!");

      有人在定义方法的参数时,可能想采用如下形式来阻止方法内部修改传进来的参数对象:

       public void method(final StringBuffer param){

       }

      实际上,这是办不到的,在该方法内部仍然可以增加如下代码来修改参数对象:

       param.append("a");

23.静态变量和实例变量的区别?

答:在语法定义上的区别:静态变量前要加 static 关键字,而实例变量前则不加。

在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。

静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。

总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。

24.&和&&的区别?

答:

&运算符有两种用法:(1)按位与;(2)逻辑与。

&&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true整个表达式的值才是true。

&&之所以称为短路运算是因为,如果&&左边的表达式的值是false,右边的表达式会被直接短路掉,不会进行运算。很多时候我们可能都需要用&&而不是&,

例如在验证用户登录时判定用户名不是null而且不是空字符串,应当写为:username != null &&!username.equals(""),二者的顺序不能交换,更不能用&运算符,因为第一个条件如果不成立,

根本不能进行字符串的equals比较,否则会产生NullPointerException异常。注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。

25.父类的静态方法能否被子类重写?

答:不能。重写只适用于实例方法,不能用于静态方法,而子类当中含有和父类相同签名的静态方法,我们一般称之为隐藏,调用的方法为定义的类所有的静态方法

26.什么是不可变对象?

答:不可变对象指对象一旦被创建,状态就不能再改变。任何修改都会创建一个新的对象,如 String、Integer及其它包装类。

27.能否创建一个包含可变对象的不可变对象?

答:可以,不过需要谨慎一点,不要共享可变对象的引用就可以了,如果需要变化时,就返回原对象的一个拷贝。

最常见的例子就是对象中包含一个String对象的引用.

28.Java 反射是指什么?它的使用场景及其优缺点分别什么?

答:Java 反射是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;

这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

使用场景:主要用于根据运行时信息来发现该类/对象/方法/属性的场景,典型的场景比如 Spring 等框架的配置、动态代理等。其原理主要是通过访问装载到JVM 中的类信息,来获取类/对象/方法/属性等信息

优点:通过在运行期访问装载到 JVM 中的类信息,来动态获取类的属性方法等信息,从而根据业务参数动态执行方法、访问属性,提高了 java 语言的灵活性和扩展性。

典型就是 Spring 等应用框架。而其他常用的高级语言如C/C++不具备这样的能力;可以提高代码复用率。

缺点:性能较差,通常慢于直接执行 java 代码; 程序的可维护性相对较差,业务代码和反射的代码交织在一起;

29.动态代理是指什么?它有哪几种实现方法?

答:动态代理是指在程序运行时生成代理类。

有两种实现方式:

 第一、JDK 动态代理,被代理对象必须实现接口,利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用 InvokeHandler 来处理;

 第二、字节码实现(比如说 cglib/asm 等),得用 ASM 开源包,将代理对象类的 class 文件加载进来,通过修改其字节码生成子类来处理

30.为什么 cglib 可以动态代理不实现接口的类?

答:

31.为什么反射的性能较差?有没有什么方法可以让他变快?

答: java反射要解析字节码,将内存中的对象进行解析,包括了一些动态类型,JVM难以优化,而且在调用时还需要拼接参数,执行步骤也更多。因此,反射操作的效率要更低

常用的改进性能方法主要有:

m.setAccessible(true);

由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的;

用缓存将反射得到的元数据保存起来;

利用一些高性能的反射库,如ReflectASM ReflectASM 使用字节码生成的方式实现了更为高效的反射机制。执行时会生成一个存取类来 set/get 字段,访问方法或创建实例。

一看到 ASM 就能领悟到 ReflectASM 会用字节码生成的方式,而不是依赖于 Java 本身的反射机制来实现的,所以它更快,并且避免了访问原始类型因自动装箱而产生的问题。

32.java当中的四种引用分别指什么?

答:

强引用,软引用,弱引用,虚引用。不同的引用类型主要体现在GC上:

强引用:如果一个对象具有强引用,它就不会被垃圾回收器回收。即使当前内存空间不足,JVM也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象;

软引用:在使用软引用时,如果内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收,只有在内存不足时,软引用才会被垃圾回收器回收;

弱引用:具有弱引用的对象拥有的生命周期更短暂。因为当 JVM 进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象;

虚引用:顾名思义,就是形同虚设,如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收;

33.为什么要有不同的引用类型?

答:

Java语言有时需要我们适当的控制对象被回收的时机,因此就诞生了不同的引用类型,可以说不同的引用类型实则是对GC回收时机不可控的妥协。比如说以下应用场景:

利用软引用和弱引用解决OOM问题:用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的空间,从而有效地避免了OOM的问题;

34.虚拟机是如何实现多态的?

答:

动态绑定技术(dynamic binding),执行期间判断所引用对象的实际类型,根据实际类型调用对应的方法.

35.静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?

答:Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。而通常的内部类需要在外部类实例化后才能实例化

36.内部类的作用

答:内部类可以有多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。在单个外围类当中,可以让多个内部类以不同的方式实现同一接口,或者继承同一个类.

创建内部类对象的时刻不依赖于外部类对象的创建.内部类并没有令人疑惑的”is-a”关系,它就像是一个独立的实体。内部类提供了更好的封装,除了该外围类,其他类都不能访问

37.3*0.1==0.3返回值是什么

答:false,因为有些浮点数不能完全精确的表示出来

38.a=a+b与a+=b有什么区别吗?

答:+=操作符会进行隐式自动类型转换,此处a+=b隐式的将加操作的结果类型强制转换为持有结果的类型,而a=a+b则不会自动进行类型转换。

举个例子,如: byte a = 23; byte b = 22; b = a + b;//编译出错 而 b += a; // 编译OK

39.int 和Integer谁占用的内存更多?

答:Integer 对象会占用更多的内存。Integer是一个对象,需要存储对象的元数据。但是int是一个原始类型的数据,所以占用的空间更少;

40.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 有那么紧密的关系。

41.Java 泛型类在什么时候确定类型?

答:在编译期间确定变量类型。类型擦除。

42.引用类型是占用几个字节?

答:hotspot在64位平台上,占8个字节,在32位平台上占4个字节。

43.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、化繁为简,一个命令编译运行源代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值