1.请说出Java14版本中更新的重要功能?
1)switch表达式
2)instanceof增强表达式,预览功能
3)文本块,第二次预览
4)Records,预览功能
2.请说出Java13版本中更新的重要功能?
1)文本块,预览功能.
2)switch表达式,预览功能.
3)Java Socket 重新实现
4)FileSystems.newFileSystem()方法
5)支持Unicode 12.1
6)可伸缩,低延迟的垃圾收集器改进,用于返回未使用的内存.
3.请说出Java12版本中重要的更新功能?
1)JVM的更新
2)File.mismatch()方法
3)紧凑型数字格式
4)String类新增了一些方法,比如indent()
4.请说出Java11版本中更新的重要功能?
1)可以直接使用Java命令运行Java程序,源代码将会隐式编译和运行.
2)String类新增了一些方法,比如说isBlank(),lines(),strip()等待.
3)Files类新增了两个读写方法,readString()和writeString().
4)可以在Lambda表达式中使用var作为变量类型.
5.请说出Java10版本中更新的重要功能?
1)局部变量类型推断,举个例子:var list = new ArrayList();可以使用var来作为变量类型,Java编译器知道list的类型为字符串的ArrayList;
2)增强java.util.Locale.
3)提供了一种默认的根证书颁发机构(CA)
6.请说出Java9版本中更新的重要功能?
1)模块系统
2)不可变的List,Set,Map的工厂方法
3)接口中可以有私有方法
4)垃圾收集器的改进
7.请说出Java8版本中更新的重要功能?
1)函数式编程和Lambda表达式
2)Stream流
3)Java Date Time API
4)接口中可以使用默认方法和静态方法
8.Java面向对象编程中的一些重要概念?
1)抽象
2)封装
3)多态
4)继承
9.什么是JVM?
JVM(Java Virtual Machine)俗称Java虚拟机,之所以称为虚拟机,是因为它实际上并不存在,它提供了一种运行环境,可供Java字节码在上面运行.
JVM提供了以下操作:
1)加载字节码
2)验证字节码
3)执行字节码
4)提供运行时环境
JVM定义了一下内容:
1)存储区
2)类文件格式
3)寄存器组
4)垃圾回收堆
5)致命错误报告等.
JVM的内部结构,它包含了类加载器(ClassLoader),运行时数据区(Runtime Data Areas)和执行引擎(Excution Engine).
1)类加载器:
类加载器是 JVM 的一个子系统,用于加载类文件。每当我们运行一个 Java 程序,它都会由类加载器首先加载。Java 中有三个内置的类加载器:
启动类加载器(Bootstrap Class-Loader),加载 jre/lib
包下面的 jar 文件,比如说常见的rt.jar(包含了 Java 标准库下的所有类文件,比如说 java.lang
包下的类,java.net
包下的类,ja
va.util
包下的类,java.io
包下的类,java.sql
包下的类)。
扩展类加载器(Extension or Ext Class-Loader),加载 jre/lib/ext
包下面的 jar 文件。
应用类加载器(Application or App Clas-Loader),根据程序的类路径(classpath)来加载 Java类。
一般来说,Java 程序员并不需要直接同类加载器进行交互。JVM 默认的行为就已经足够满足大多数情况的需求了。不过,如果遇到了需要和类加载器进行交互的情况,而对类加载器的机制又不是很了解的话,就不得不花大量的时间去调试ClassNotFoundException 和 NoClassDefFoundError
等异常。
对于任意一个类,都需要由它的类加载器和这个类本身一同确定其在 JVM 中的唯一性。也就是说,如果两个类的加载器不同,即使两个类来源于同一个字节码文件,那这两个类就必定不相等(比如两个类的 Class对象不 equals
)。
通过一段简单的代码了解下。
public class Test { public static void main(String[] args) { ClassLoader loader = Test.class.getClassLoader(); while (loader != null) { System.out.println(loader.toString()); loader = loader.getParent(); } } }
每个 Java 类都维护着一个指向定义它的类加载器的引用,通过 类名.class.getClassLoader()
可以获取到此引用;然后通过 loader.getParent()
可以获取类加载器的上层类加载器。
上面这段代码的输出结果如下:
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@4617c264
第一行输出为 Test 的类加载器,即应用类加载器,它是 sun.misc.Launcher$AppClassLoader
类的实例;
第二行输出为扩展类加载器,是 sun.misc.Launcher$ExtClassLoader
类的实例。那启动类加载器呢?
按理说,扩展类加载器的上层类加载器是启动类加载器,但在我这个版本的 JDK 中, 扩展类加载器的 get
Parent()
返回 null
。所以没有输出。
2)运行时数据区
运行时数据区又包含以下内容。
PC寄存器(PC Register),也叫程序计数器(Program Counter Register),是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器,线程私有。
JVM 栈(Java Virtual Machine Stack),与 PC 寄存器一样,JVM 栈也是线程私有的。每一个JVM 线程都有自己的 JVM 栈,这个栈与线程同时创建,它的生命周期与线程相同。
本地方法栈(Native Method Stack),JVM 可能会使用到传统的栈来支持 Native 方法(使用Java 语言以外的其它语言[C语言]编写的方法)的执行,这个栈就是本地方法栈。
堆(Heap),在 JVM 中,堆是可供各条线程共享的运行时内存区域,也是供所有类实例和数据对象分配内存的区域。
方法区(Method area),在 JVM 中,被加载类型的信息都保存在方法区中。包括类型信息(TypeInformation)和方法列表(Method Tables)。方法区是所有线程共享的,所以访问方法区信息的方法必须是线程安全的。
运行时常量池(Runtime Constant Pool),运行时常量池是每一个类或接口的常量池在运行时的表现形式,它包括了编译器可知的数值字面量,以及运行期解析后才能获得的方法或字段的引用。简而言之,当一个方法或者变量被引用时,JVM 通过运行时常量区来查找方法或者变量在内存里的实际地址。
3)执行引擎
执行引擎包含了:
解释器:读取字节码流,然后执行指令。因为它一条一条地解释和执行指令,所以它可以很快地解释字节码,但是执行起来会比较慢。
即时(Just-In-Time,JIT)编译器:即时编译器用来弥补解释器的缺点,提高性能。执行引擎首先按照解释执行的方式来执行,然后在合适的时候,即时编译器把整段字节码编译成本地代码。然后,执行引擎就没有必要再去解释执行方法了,它可以直接通过本地代码去执行。执行本地代码比一条一条进行解释执行的速度快很多。编译后的代码可以执行的很快,因为本地代码是保存在缓存里的。
10.JDK和JVM有什么区别?
JDK 是 Java Development Kit 的首字母缩写,是提供给 Java 开发人员的软件环境,包含 JRE 和一组开发工具。可分为以下版本:
标准版(大多数开发人员用的就是这个)
企业版
微型版
JDK 包含了一个私有的 JVM 和一些其他资源,比如说编译器(javac 命令)、解释器(java 命令)等,帮助 Java 程序员完成开发工作。
11.JVM和JRE有什么区别?
Java Runtime Environment(JRE)是 JVM 的实现。JRE 由 JVM 和 Java 二进制文件以及其他类组成,可以执行任何程序。JRE 不包含 Java 编译器,调试器等任何开发工具。
12.Java中main()方法的重要性是什么?
每个程序都需要一个入口,对于 Java 程序来说,入口就是 main 方法。
public static void main(String[] args) {}
public 关键字是另外一个访问修饰符,除了可以声明方法和变量(所有类可见),还可以声明类。main()
方法必须声明为 public。
static 关键字表示该变量或方法是静态变量或静态方法,可以直接通过类访问,不需要实例化对象来访问。
void 关键字用于指定方法没有返回值。
另外,main 关键字为方法的名字,Java 虚拟机在执行程序时会寻找这个标识符;args 为 main()
方法的参数名,它的类型为一个 String 数组,也就是说,在使用 java 命令执行程序的时候,可以给 main()
方法传递字符串数组作为参数。
java HelloWorld 沉默王二 沉默王三//启动类的main方法时传递了两个字符串参数
javac 命令用来编译程序,java 命令用来执行程序,HelloWorld 为这段程序的类名,沉默王二和沉默王三为字符串数组,中间通过空格隔开,然后就可以在 main()
方法中通过 args[0]
和 args[1]
获取传递的参数值了。
public class HelloWorld { public static void main(String[] args) { if ("沉默王二".equals(args[0])) { } if ("沉默王三".equals(args[1])) { } } }
13.Java的重载(Overload)和重写(Override)有什么区别?
class LaoWang{ public void write() { System.out.println("老王写了一本《基督山伯爵》"); } } public class XiaoWang extends LaoWang { @Override public void write() { System.out.println("小王写了一本《茶花女》"); } }
重写的两个方法名相同,方法参数的个数也相同;不过一个方法在父类中,另外一个在子类中。就好像父类LaoWang 有一个 write()
方法(无参),方法体是写一本《基督山伯爵》;子类 XiaoWang 重写了父类的 write()
方法(无参),但方法体是写一本《茶花女》。
测试代码:
public class OverridingTest { public static void main(String[] args) { LaoWang wang = new XiaoWang(); wang.write(); } }
测试结果:
小王写了一本《茶花女》
在上面的代码中,们声明了一个类型为 LaoWang 的变量 wang。在编译期间,编译器会检查 LaoWang类是否包含了 write()
方法,发现 LaoWang 类有,于是编译通过。在运行期间,new 了一个XiaoWang 对象,并将其赋值给 wang,此时 Java 虚拟机知道 wang 引用的是 XiaoWang 对象,所以调用的是子类 XiaoWang 中的 write()
方法而不是父类 LaoWang 中的 write()
方法,因此输出结果为“小王写了一本《茶花女》”。
再来看一段重载的代码吧。
class LaoWang{ public void read() { System.out.println("老王读了一本《Web全栈开发进阶之路》"); } public void read(String bookname) { System.out.println("老王读了一本《" + bookname + "》"); } }
原文:https://www.cnblogs.com/wk-missQ1/p/13259863.html