62道Java核心面试题,打包送给爱学习的你

文章资讯 2020-07-16 20:28:56

62道Java核心面试题,打包送给爱学习的你

准备了62道Java核心面试题,希望能够帮助到大家,以及其他类似情况的读者朋友。01、请说出Java14版本中更新的重要功能
instanceof增强表达式,预览功能
文本块,第二次预览
Records,预览功能刚好我之前写过一篇文章,关于Java14的开箱体验,很香,读者朋友需要的话,可以点下面的链接看一看。
Java14开箱,它真香香香香
02、请说出Java13版本中更新的重要功能
Java13发布于2019年9月17日,更新的重要功能有:文本块,预览功能
switch表达式,预览功能
JavaSocket重新实现
FileSystems.newFileSystem()方法
支持Uni12.1
可伸缩、低延迟的垃圾收集器改进,用于返回未使用的内存03、请说出Java12版本中更新的重要功能
Java12发布于2019年3月19日,更新的重要功能有:JVM更新
File.mismatch()方法
紧凑型数字格式
Sing类新增了一些方法,比如说indent()04、请说出Java11版本中更新的重要功能
Java11是继Java8之后的第二个商用版本,如果你下载的是OracleJDK,则需要进行付费;如果想继续使用免费版本,需要下载OenJDK。OracleJDK中会有一些OenJDK没有的、商用闭源的功能。
Java11更新的重要功能有:可以直接使用java命令运行Java程序,源代码将会隐式编译和运行。
Sing类新增了一些方法,比如说isBlank()、nes()、si()等等。
Files类新增了两个读写方法,adSing()和writeSing()。
可以在Lambda表达式中使用var作为变量类型。05、请说出Java10版本中更新的重要功能
Java10更新的重要功能有:局部变量类型推断,举个例子,varst=newArrayList<Sing>();,可以使用var来作为变量类型,Java编译器知道st的类型为字符串的ArrayList。
增强java.util.Locale。
提供了一组默认的根证书颁发机构(CA)。06、请说出Java9版本中更新的重要功能
Java9更新的重要功能有:模块系统
不可变的List、Set、Ma的工厂方法
接口中可以有私有方法
垃圾收集器改进07、请说出Java8版本中更新的重要功能
Java8发布于2014年3月份,可以说是Java6之后最重要的版本更新,深受开发者的喜爱。函数式编程和Lambda表达式
Seam流
JavaDateTimeAPI
接口中可以使用默认方法和静态方法我强烈建议点开上面的链接阅读以下,以正确理解这些概念。
08、请说出Java面向对象编程中的一些重要概念抽象
封装
多态
继承09、Java声称的平台独立性指的是什么?
常见的操作系统有Windows、Linux、OS-X,那么平台独立性意味着我们可以在任何操作系统中运行相同源代码的Java程序,比如说我们可以在Windows上编写Java程序,然后在Linux上运行它。
10、什么是JVM?
JVM(JavaVirtualMachine)俗称Java虚拟机。之所以称为虚拟机,是因为它实际上并不存在。它提供了一种运行环境,可供Java字节码在上面运行。
JVM提供了以下操作:加载字节码
验证字节码
执行字节码
提供运行时环境JVM定义了以下内容:存储区
类文件格式
寄存器组
垃圾回收堆
致命错误报告等我们来尝试理解一下JVM的内部结构,它包含了类加载器(ClassLoader)、运行时数据区(RuntimeDataAas)和执行引擎(ExcutionEngine)。1)类加载器
类加载器是JVM的一个子系统,用于加载类文件。每当我们运行一个Java程序,它都会由类加载器首先加载。Java中有三个内置的类加载器:
启动类加载器(BootsaClass-Loader),加载jb包下面的jar文件,比如说常见的rt.jar(包含了Java标准库下的所有类文件,比如说java.lang包下的类,java.net包下的类,java.util包下的类,java.io包下的类,java.sql包下的类)。
扩展类加载器(ExtensionorExtClass-Loader),加载jbext包下面的jar文件。
应用类加载器(AcationorAClas-Loader),根据程序的类路径(classa)来加载Java类。
一般来说,Java程序员并不需要直接同类加载器进行交互。JVM默认的行为就已经足够满足大多数情况的需求了。不过,如果遇到了需要和类加载器进行交互的情况,而对类加载器的机制又不是很了解的话,就不得不花大量的时间去调试
ClassNotFoundExcetion和NoClassDefFoundError等异常。
对于任意一个类,都需要由它的类加载器和这个类本身一同确定其在JVM中的唯一性。也就是说,如果两个类的加载器不同,即使两个类来源于同一个字节码文件,那这两个类就必定不相等(比如两个类的Class对象不equals)。
是不是有点晕,来来来,通过一段简单的代码了解下。
ubcclassTest{ ubcstaticvoidmain(Sing[]args){
ClassLoaderloader=Test.class.getClassLoader();
while(loader!=nl){
System.out.rintln(loader.toSing());
loader=loader.getPant();
}
}}每个Java类都维护着一个指向定义它的类加载器的引用,通过类名.class.getClassLoader()可以获取到此引用;然后通过loader.getPant()可以获取类加载器的上层类加载器。
上面这段代码的输出结果如下:
sun.misc.Launcher$AClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@4617c264第一行输出为Test的类加载器,即应用类加载器,它是sun.misc.Launcher$AClassLoader类的实例;第二行输出为扩展类加载器,是sun.misc.Launcher$ExtClassLoader类的实例。那启动类加载器呢?
按理说,扩展类加载器的上层类加载器是启动类加载器,但在我这个版本的JDK中,扩展类加载器的getPant()返回nl。所以没有输出。
2)运行时数据区
运行时数据区又包含以下内容。PC寄存器(PCRegister),也叫程序计数器(ProgramCounterRegister),是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器。
JVM栈(JavaVirtualMachineStack),与PC寄存器一样,JVM栈也是线程私有的。每一个JVM线程都有自己的JVM栈,这个栈与线程同时创建,它的生命周期与线程相同。
本地方法栈(NativeMeodStack),JVM可能会使用到传统的栈来支持Native方法(使用Java语言以外的其它语言[C语言]编写的方法)的执行,这个栈就是本地方法栈。
堆(Hea),在JVM中,堆是可供各条线程共享的运行时内存区域,也是供所有类实例和数据对象分配内存的区域。
方法区(Meodaa),在JVM中,被加载类型的信息都保存在方法区中。包括类型信息(TyeInformation)和方法列表(MeodTables)。方法区是所有线程共享的,所以访问方法区信息的方法必须是线程安全的。
运行时常量池(RuntimeConstantPool),运行时常量池是每一个类或接口的常量池在运行时的表现形式,它包括了编译器可知的数值字面量,以及运行期解析后才能获得的方法或字段的引用。简而言之,当一个方法或者变量被引用时,JVM通过运行时常量区来查找方法或者变量在内存里的实际地址。
3)执行引擎
执行引擎包含了:
解释器:读取字节码流,然后执行指令。因为它一条一条地解释和执行指令,所以它可以很快地解释字节码,但是执行起来会比较慢。
即时(Just-In-Time,JIT)编译器:即时编译器用来弥补解释器的缺点,提高性能。执行引擎首先按照解释执行的方式来执行,然后在合适的时候,即时编译器把整段字节码编译成本地代码。然后,执行引擎就没有必要再去解释执行方法了,它可以直接通过本地代码去执行。执行本地代码比一条一条进行解释执行的速度快很多。编译后的代码可以执行的很快,因为本地代码是保存在缓存里的。
11、JDK和JVM有什么区别?
JDK是JavaDevelomentKit的首字母缩写,是提供给Java开发人员的软件环境,包含JRE和一组开发工具。可分为以下版本:标准版(大多数开发人员用的就是这个)
企业版
微型版JDK包含了一个私有的JVM和一些其他资源,比如说编译器(javac命令)、解释器(java命令)等,帮助Java程序员完成开发工作。12、JVM和JRE有什么区别?
JavaRuntimeEnvironment(JRE)是JVM的实现。JRE由JVM和Java二进制文件以及其他类组成,可以执行任何程序。JRE不包含Java编译器,调试器等任何开发工具。13、哪个类是所有类的超类?
java.lang.Object是所有Java类的超类,我们不需要继承它,因为是隐式继承的。
14、为什么Java不支持多重继承?
如果有两个类共同继承(extends)一个有特定方法的父类,那么该方法会被两个子类重写。然后,如果你决定同时继承这两个子类,那么在你调用该重写方法时,编译器不能识别你要调用哪个子类的方法。这也正是著名的菱形问题,见下图。ClassC同时继承了ClassA和ClassB,ClassC的对象在调用ClassA和ClassB中重载的方法时,就不知道该调用ClassA的方法,还是ClassB的方法。
15、为什么Java不是纯粹的面向对象编程语言?
之所以不能说Java是纯粹的面向对象编程语言,是因为Java支持基本数据类型,比如说int、short、long、double等,尽管它们有自己的包装器类型,但它们的确不能算是对象。
16、a和classa之间有什么区别?
a是操作系统用来查找可执行文件的环境变量,我的电脑上就定义了下图这些a变量,比如Java和Maven的。classa是针对Java而言的,用于指定Java虚拟机载入的字节码文件路径。
17、Java中main()方法的重要性是什么?
每个程序都需要一个入口,对于Java程序来说,入口就是main方法。
ubcstaticvoidmain(Sing[]args){}ubc关键字是另外一个访问修饰符,除了可以声明方法和变量(所有类可见),还可以声明类。main()方法必须声明为ubc。
static关键字表示该变量或方法是静态变量或静态方法,可以直接通过类访问,不需要实例化对象来访问。
void关键字用于指定方法没有返回值。
另外,main关键字为方法的名字,Java虚拟机在执行程序时会寻找这个标识符;args为main()方法的参数名,它的类型为一个Sing数组,也就是说,在使用java命令执行程序的时候,可以给main()方法传递字符串数组作为参数。
javaHelloWorld沉默王二沉默王三javac命令用来编译程序,java命令用来执行程序,HelloWorld为这段程序的类名,沉默王二和沉默王三为字符串数组,中间通过空格隔开,然后就可以在main()方法中通过args[0]和args[1]获取传递的参数值了。
ubcclassHelloWorld{
ubcstaticvoidmain(Sing[]args){
if("沉默王二".equals(args[0])){}if("沉默王三".equals(args[1])){}
}
}main()方法的写法并不是唯一的,还有其他几种变体,尽管它们可能并不常见,可以简单来了解一下。
第二种,把方括号[]往args靠近而不是Sing靠近:
ubcstaticvoidmain(Sing[]args){}第三种,把方括号[]放在args的右侧:
ubcstaticvoidmain(Singargs[]){}第四种,还可以把数组形式换成可变参数的形式:
ubcstaticvoidmain(Sing...args){}第五种,在main()方法上添加另外一个修饰符sictf,用于强调在处理浮点数时的兼容性:
ubcsictfstaticvoidmain(Sing[]args){}也可以在main()方法上添加final关键字或者synconized关键字。
第六种,还可以为args参数添加final关键字:
ubcstaticvoidmain(finalSing[]args){}第七种,最复杂的一种,所有可以添加的关键字统统添加上:
finalstaticsynconizedsictfvoidmain(finalSing[]args){}当然了,并不需要为了装逼特意把main()方法写成上面提到的这些形式,使用IDE提供的默认形式就可以了。
18、Java的重写(Override)和重载(Overload)有什么区别?
先来看一段重写的代码吧。
classLaoWang{
ubcvoidwrite(){
System.out.rintln("老王写了一本《基督山伯爵》");
}
}
ubcclassXiaoWangextendsLaoWang{
@Override
ubcvoidwrite(){
System.out.rintln("小王写了一本《茶花女》");
}
}重写的两个方法名相同,方法参数的个数也相同;不过一个方法在父类中,另外一个在子类中。就好像父类LaoWang有一个write()方法(无参),方法体是写一本《基督山伯爵》;子类XiaoWang重写了父类的write()方法(无参),但方法体是写一本《茶花女》。
来写一段测试代码。
ubcclassOverridingTest{
ubcstaticvoidmain(Sing[]args){
LaoWangwang=newXiaoWang();
wang.write();
}
}大家猜结果是什么?
小王写了一本《茶花女》在上面的代码中,们声明了一个类型为LaoWang的变量wang。在编译期间,编译器会检查LaoWang类是否包含了write()方法,发现LaoWang类有,于是编译通过。在运行期间,new了一个XiaoWang对象,并将其赋值给wang,此时Java虚拟机知道wang引用的是XiaoWang对象,所以调用的是子类XiaoWang中的write()方法而不是父类LaoWang中的write()方法,因此输出结果为“小王写了一本《茶花女》”。
再来看一段重载的代码吧。
classLaoWang{
ubcvoidad(){
System.out.rintln("老王读了一本《Web全栈开发进阶之路》");
}ubcvoidad(Singbookname){
System.out.rintln("老王读了一本《"+bookname+"》");
}
}重载的两个方法名相同,但方法参数的个数不同,另外也不涉及到继承,两个方法在同一个类中。就好像类LaoWang有两个方法,名字都是ad(),但一个有参数(书名),另外一个没有(只能读写死的一本书)。
来写一段测试代码。
ubcclassOverloadingTest{
ubcstaticvoidmain(Sing[]args){
LaoWangwang=newLaoWang();
wang.ad();
wang.ad("金瓶梅");
}
}这结果就不用猜了。变量wang的类型为LaoWang,wang.ad()调用的是无参的ad()方法,因此先输出“老王读了一本《Web全栈开发进阶之路》”;wang.ad("金瓶")调用的是有参的ad(bookname)方法,因此后输出“老王读了一本《金瓶》”。在编译期间,编译器就知道这两个ad()方法时不同的,因为它们的方法签名(=方法名称+方法参数)不同。
简单的来总结一下:
1)编译器无法决定调用哪个重写的方法,因为只从变量的类型上是无法做出判断的,要在运行时才能决定;但编译器可以明确地知道该调用哪个重载的方法,因为引用类型是确定的,参数个数决定了该调用哪个方法。
2)多态针对的是重写,而不是重载。如果在一个类中有多个相同名字的方法,但参数不同,则称为方法重载。
父类中有一个方法,子类中有另外一个和它有相同签名(方法名相同,参数相同、修饰符相同)的方法时,则称为方法重写。子类在重写父类方法的时候可以加一个@Override注解。
19、main()方法可以重载吗?
可以,一个类中可以有多个名称为“main”的方法:
ubcclassMainTest{
ubcstaticvoidmain(Sing[]args){
System.out.rintln("main(Sing[]args)");
}ubcstaticvoidmain(Sing[]args,Singarg){
System.out.rintln("(Sing[]args,Singarg");
}
}但该类在运行的时候,只会找到一个入口,即ubcstaticvoidmain(Sing[]args)。
20、一个Java源文件中有多个ubc类吗?
一个Java源文件中不能有多个ubc类。21、什么是Java的ackage(包)?
在Java中,我们使用ackage(包)对相关的类、接口和子包进行分组。这样做的好处有:使相关类型更容易查找
避免命名冲突,比如说com.itwanger.Hello和com.itwang.Hello不同
通过包和访问权限控制符来限定类的可见性可以使用ackage关键字来定义一个包名,需要注意的是,这行代码必须处于一个类中的第一行。强烈建议在包中声明类,不要缺省,否则就失去了包结构的带来的好处。
包的命名应该遵守以下规则:应该全部是小写字母
可以包含多个单词,单词之间使用“.”连接,比如说java.lang
名称由公司名或者组织名确定,采用倒序的方式,比如说,我个人博客的域名是www.itwanger.com,所以我创建的包名是就是com.itwanger.xxxx。每个包或者子包都在磁盘上有自己的目录结构,如果Java文件时在com.itwanger.xxxx包下,那么该文件所在的目录结构就应该是com->itwanger->xxxx。
默认情况下,java.lang包是默认导入的,我们不需要显式地导入该包下的任何类。
ackagecom.cmower.bb;ubcclassPackageTest{
ubcstaticvoidmain(Sing[]args){
Boolean.toSing(ue);
}
}Boolean类属于java.lang包,当使用它的时候并不需要显式导入。
22、什么是访问权限修饰符?
访问权限修饰符对于Java来说,非常重要,目前共有四种:ubc、rivate、rotected和defat(缺省)。
一个类只能使用ubc或者defat修饰,ubc修饰的类你之前已经见到过了,现在我来定义一个缺省权限修饰符的类给你欣赏一下。
classDog{
}哈哈,其实也没啥可以欣赏的。缺省意味着这个类可以被同一个包下的其他类进行访问;而ubc意味着这个类可以被所有包下的类进行访问。
假如硬要通过rivate和rotected来修饰类的话,编译器会生气的,它不同意。rivate可以用来修饰类的构造方法、字段和方法,只能被当前类进行访问。rotected也可以用来修饰类的构造方法、字段和方法,但它的权限范围更宽一些,可以被同一个包中的类进行访问,或者当前类的子类。
可以通过下面这张图来对比一下四个权限修饰符之间的差别:
同一个类中,不管是哪种权限修饰符,都可以访问;
同一个包下,rivate修饰的无法访问;
子类可以访问ubc和rotected修饰的;
ubc修饰符面向世界,哈哈,可以被所有的地方访问到。23、什么是final关键字?
final关键字修饰类的时候,表示该类无法被继承。比如,Sing类就是final的,无法被继承。
final关键字修饰方法的时候,表示子类无法覆盖它。
final关键字修饰变量的时候,表示该变量只能被赋值一次,尽管变量的状态可以更改。
关于final更详细的内容,可以参照我之前写了另外一篇文章:
我去,你竟然还不会用final关键字
24、什么是static关键字?
static关键字可以用来修饰类变量,使其具有全局性,即所有对象将共享同一个变量。
static关键字可以用来修饰方法,该方法称为静态方法,只可以访问类的静态变量,并且只能调用类的静态方法。
关于static更详细的内容,可以参照我之前写了另外一篇文章:
面试官:兄弟,说说Java的static关键字吧
25、finally和finaze有什么区别?
finally通常与y-catch块一起使用,即使y-catch块引发了异常,finally块中的代码也会被执行,用于释放y块中创建的资源。
finaze()是Object类的一个特殊方法,当对象正在被垃圾回收时,垃圾收集器将会调用该方法。可以重写该方法用于释放系统资源。
26、可以将一个类声明为static的吗?
不能将一个外部类声明为static的,但可以将一个内部类声明为static的——称为静态内部类。
27、什么是静态导入?
如果必须在一个类中使用其他类的静态变量或者静态方法,通常我们需要先导入该类,然后使用“类名.变量方法”的形式调用。
imortjava.lang.Ma;doubletest=Ma.PI*5;也可以通过静态导入的方式,就不需要再使用类名了。
imortstaticjava.lang.Ma.PI;doubletest=PI*5;不过,静态导入容易引发混乱(变量名或者方法名容易冲突),因此最好避免使用静态导入。
28、什么是y-wi-sources?
y-wi-sources是Java7时引入的一个自动资源管理语句,在此之前,我们必须通过y-catch-finally的方式手动关闭资源,当我们忘记关闭资源的时候,就容易导致内存泄漏。
关于y-wi-sources更详细的内容,可以参照我之前写了另外一篇文章:
我去,你竟然还在用y–catch-finally
29、什么是mti-catch?
Java7改进的另外一个地方就是mti-catch,可以在单个catch中捕获多个异常,当一个y块抛出多个类似的异常时,这种写法更短,更清晰。
catch(IOExcetion|SQLExcetionex){
logger.error(ex);
rownewMyExcetion(ex.getMessage());
}当有多个异常的时候,可以使用管道表示符“|”隔开。
30、什么是static块?
static块是由JavaClassLoader将类加载到内存中时执行的代码块。通常用于初始化类的静态变量或者创建静态资源。
31、什么是接口?
接口是Java编程语言中的一个核心概念,不仅在JDK源码中使用很多,还在Java设计模式、框架和工具中使用很多。接口提供了一种在Java中实现抽象的方法,用于定义子类的行为约定。
关于接口更详细的内容,可以参照我之前写了另外一篇文章:
可能是把Java接口讲得最通俗的一篇文章
32、什么是抽象类?
在Java中,抽象类用于创建具有某些被子类实现的默认方法的类,一个抽象类可以有没有方法体的抽象方法,也可以有和普通类一样有方法体的方法。
absact关键字用于声明一个抽象类,抽象类无法实例化,主要用于为子类提供一个模板,子类需要覆盖抽象方法。
关于抽象类更详细的内容,可以参照我之前写了另外一篇文章:
小白,你要的Java抽象类,操碎了心
33、抽象类和接口有什么区别?声明抽象类的关键字为absact,声明接口的关键字为interface。
抽象类可以有具体的方法,接口不能。
一个类只能继承一个抽象类,但可以实现多个接口。
接口中的变量只能是隐式的常量,抽象类中可以有任意类型的变量。
如果一个抽象类有main()方法,则可以运行它;但接口不能。
抽象类是对类的一种抽象,继承抽象类的类和抽象类本身是一种is-a的关系。
接口是对类的某种行为的一种抽象,接口和类之间并没有很强的关联关系,所有的类都可以实现Seriazable接口,从而具有序列化的功能。34、一个接口可以实现或者继承另外一个接口吗?
接口不能实现另外一个接口,但可以继承一个接口。因为接口中不能有具体的方法,所以不会出现菱形问题,所以我们可以在一个接口中继承多个接口。
ubcinterfaceCextendsA,B{
}从Java8开始,接口可以有默认方法,所以当多个接口中存在相同的默认方法时,需要在实现接口的类中提供该方法的实现。
35、什么是标记接口?
标记接口是一个空的接口,没有任何方法,用于强制实现类中的某些功能。比较出名的标记接口有Seriazable接口、Cloneable接口。
关于Seriazable接口更详细的内容,可以参照我之前写了另外一篇文章:
JavaSeriazable:明明就一个空的接口嘛
36、什么是包装器类?
包装器类是Java中八种基本数据类型的对象表示形式,所有的包装器类都是不可变的,并且是final的。通过装箱和拆箱,可以将八种基本数据类型和包装器类型互相转换。
关于基本类型和包装类型更详细的内容,可以参照我之前写了另外一篇文章:
面试官:兄弟,说说基本类型和包装类型的区别吧
37、什么是枚举?
enum(枚举)是Java1.5时引入的关键字,它表示一种特殊类型的类,默认继承自java.lang.Enum。
ubcenumPlayerTye{
TENNIS,
FOOTBALL,
BASKETBALL
}enum是用于创建枚举的关键字,枚举中的常量都是隐式static和final的。
关于枚举更详细的内容,可以参照我之前写了另外一篇文章:
恕我直言,我怀疑你并不会用Java枚举
38、什么是Java注解?
注解是Java1.5时引入的,同class和interface一样,也属于一种类型,注解提供了一系列数据用来装饰程序代码(类、方法、字段等),但是注解并不是所装饰代码的一部分,它对代码的运行效果没有直接影响(这句话怎么理解呢?),由编译器决定该执行哪些操作。
关于注解更详细的内容,可以参照我之前写了另外一篇文章:
不吹牛逼,撸个注解有什么难的
39、什么是Java反射?
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有字段和方法;对于任意一个对象,都能够调用它的任意字段和方法;这种动态获取信息以及动态调用对象方法的功能称为Java反射机制。
反射属于高级主题,在常规编程中应该避免使用,因为反射可以通过调用私有的构造方法来破坏设计模式,比如说单例模式。
尽管不建议使用反射机制,但反射机制的存在至关重要,因为如果没有反射,我们将没有Sring之类的框架,甚至Tomcat之类的服务器。它们通过反射调用适当的方法并对类实例化,省去了很多麻烦。
40、Java中的组合指的什么?
通过对象组合可以实现代码的重用,Java组合是通过引用其他对象的引用来实现的,使用组合的好处就是我们可以控制其他对象对使用者的可见性,并且刻意重用我们需要的对象。
41、与继承相比,组合有什么好处?任何父类的修改都可能会影响到子类,甚至我们没有使用父类的一些方法。举个例子,假如子类有一个方法test(),而父类之前是没有的,但突然有人在不知情的情况下在父类插入了一个同名但签名不同的test()方法,那么就会出现编译错误。组合是不会遇到这个问题的,因为我们仅仅会使用我们需要的方法。这是父类追加的test()方法:
ubcclassSuer{
ubcSingtest(){
System.out.rintln("suer");
turnnl;
}
}原来子类的test()方法就出错了。来个表格列举一下两者之间的优缺点:
组合关系
继承关系
优点:不破坏封装,整体类与局部类之间松耦合,彼此相对独立
缺点:破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性
优点:具有较好的可扩展性
缺点:支持扩展,但是往往以增加系统结构的复杂度为代价
优点:支持动态组合。在运行时,整体对象可以选择不同类型的局部对象
缺点:不支持动态继承。在运行时,子类无法选择不同的父类
优点:整体类可以对局部类进行包装,封装局部类的接口,提供新的接口
缺点:子类不能改变父类的接口
缺点:整体类不能自动获得和局部类同样的接口
优点:子类能自动继承父类的接口
缺点:创建整体类的对象时,需要创建所有局部类的对象
优点:创建子类的对象时,无须创建父类的对象
42、如何在Java中对自定义对象的集合进行排序?
需要对自定义对象的类实现Comarable接口,重写comaTo(Tobj)方法,该方法在排序的时候会被调用进行排序。
关于Comarable和Comarator接口更详细的内容,可以参照我之前写了另外一篇文章:
一文彻底搞懂Java中的Comarable和Comarator
43、什么是内部类?
我们可以在一个类中定义一个类,这个类被称为内部类。内部类可以访问外部类的所有变量和方法,内部类中不能有任何静态变量。
44、什么是匿名内部类?
没有名称的内部类称为匿名内部类,它通过单个语句进行定义和实例化,总是需要扩展一个类或者实现一个接口。
由于匿名内部类没有名称,所以无法为匿名内部类定义构造方法。
45、什么是Java中的Classloader(类加载器)?
当我们要访问任何类时,都需要通过JavaClassloader将该类的字节码加在到内存当中,可以通过继承ClassLoader并重写loadClass(Singname)方法来创建自定义的类加载器。
46、有哪些不同的类加载器?
Bootsa类加载器,用来加在JDK的内部类,比如说rt.jar。
Extensions类加载器,它从JDK扩展目录(JAVA_HOMEbext)中加载类。
System类加载器,它从当前类路径加载类。
47、什么是三元运算符?
三元运算符是if-en-else语句的一个替换,示例如下:
st=testStatement?value1:value2;48、suer关键字有什么用?
当在子类中重写了父类方法时,可以通过suer关键字访问父类方法。
也可以使用suer关键字在子类构造方法中调用父类构造方法,它必须是构造方法中的第一条语句。
ubcclassSuerClass{ ubcSuerClass(){
}

ubcSuerClass(inti){}

ubcvoidtest(){
System.out.rintln("父类的测试方法");
}
}来看子类中如何使用suer关键字:
ubcclassChildClassextendsSuerClass{ ubcChildClass(Sings){
调用父类的构造方法
suer();

调用子类的test方法
test();

使用suer关键字调用父类的test方法
suer.test();
}

@Override
ubcvoidtest(){
System.out.rintln("childclasstestmeod");
}
}49、什么是eak,什么是continue?
我们可以使用eak关键字终止for、while、do-while循环;可以在switch语句中使用eak退出case条件。
我们可以使用continue关键字在for、while、do-while循环跳过当前迭代;甚至可以使用带有标签的continue语句来跳过最外层循环的当前迭代。
50、什么是is关键字?
is关键字提供对当前对象的引用,主要用于确保使用了当前对象的变量,而不是具有相同名称的局部变量。
consuctor
ubcPoint(intx,inty){
is.x=x;
is.y=y;
}还可以使用is关键字在构造方法中调用其他构造方法:
ubcRectangle(){
is(0,0,0,0);
}
ubcRectangle(intwid,intheight){
is(0,0,wid,height);
}
ubcRectangle(intx,inty,intwid,intheight){
is.x=x;
is.y=y;
is.wid=wid;
is.height=height;
}关于is关键字更详细的内容,可以参照我之前写了另外一篇文章:
我去,你竟然还不会用is关键字
51、什么是默认的构造方法?
一个类的无参构造方法被称为默认构造方法。当我们没有为一个类定义构造方法时,Java编译器会自动为该类创建一个默认的无参构造方法。如果定义了其他构造方法,编译器就不会在为我们创建默认构造方法了。
52、y块可以没有catch吗?
是的,可以直接使用y-finally,而不需要catch捕获异常。
53、什么是垃圾回收?
垃圾回收(GarbageCollection,简称GC)会查看堆内存,识别正在使用和未使用的对象,以及会自动删除未使用的对象,用来释放内存。
54、什么是序列化和反序列化?
我们可以把一个Java对象转化成一个数据流,这被称为序列化。一旦对象被转化为数据流后,就可以将其保存到文件或者通过网络套接字发送。
如果一个对象实现了Seriazable接口,就可以使用java.io.ObjectOututSeam将对象写入文件。
将数据流再转化为Java对象被称为反序列化。
55、如何通过命令提示符运行jar文件?
可以通过java命令运行jar文件,但需要jar文件中有main方法。
56、System类有什么用?
System类是Java的一个核心类,比较常用的就是System.out.rintln()。
System类是final的,因此我们不能通过继承来重写它的方法,System类没有提供任何ubc的构造方法,因此无法实例化,它的所有方法都是static的。
57、什么是instanceof关键字?
我们可以使用instanceof关键字检查对象是否属于一个类。
ubcstaticvoidmain(Singargs[]){
Objects=newSing("沉默王二");

if(sinstanceofSing){
System.out.rintln("字符串值为:"+s);
}

if(sinstanceofInteger){
System.out.rintln("数字的值是:"+s);
}
}58、可以在switch中使用字符串吗?
Java7改进的一个功能就是允许在switch语句中使用字符串。
关于switch更详细的内容,可以参照我之前写了另外一篇文章:
我去,你写的switch语句也太老土了吧
59、Java是按值传递还是按引用传递?
可以很确定地说,Java是按值传递的。
关于这个问题,可以参照我之前写了另外一篇文章:
面试官:兄弟,说说Java到底是值传递还是引用传递
60、堆(hea)和栈(stack)有什么区别?堆内存被应用程序的所有部分使用,而栈内存仅由执行线程使用。
当我们创建对象时,它始终存储在堆空间上;栈仅存储该对象的引用,栈内存还可以存储局部的基本类型数据变量。
栈的内存管理方式是LIFO(后进先出)形式,而堆的内存管理方式更复杂。61、Java编译在JDK中,还是JRE,还是JVM中?
Java编译器的任务是将Java源代码转换为字节码,可以通过javac命令执行,因此它在JDK中,JRE中不需要它。
62、下面这段程序输出什么?
ubcclassTest{ ubcstaticSingtoSing(){
System.out.rintln("测试toSing方法有没有被调用");
turn"";
}

ubcstaticvoidmain(Singargs[]){
System.out.rintln(toSing());
}
}这段代码无法编译通过,因为java.lang.Object中的toSing()方法不是static的,它无法被static修饰的方法重写。
那下面这段代码呢?
ubcclassTest{
ubcstaticSingfoo(){
System.out.rintln("测试foo方法有没有被调用");
turn"";
}ubcstaticvoidmain(Singargs[]){
Testobj=nl;
System.out.rintln(obj.foo());
}
}这段代码会输出测试foo方法有没有被调用,没有出现NlPointerExcetion。为什么呢?
命名obj为nl啊,通过obj调用foo()方法的时候应该抛出NlPointerExcetion异常才对啊!
之所以没有抛出异常,是因为Java编译器对这段代码做出了优化,因为foo()方法是静态方法,所以obj.foo()会被优化为foo(),所以就不会抛出异常了。
来看一下这段代码的字节码就明白了:
ubcclassTest{
ubcTest(){
}ubcstaticSingfoo(){
System.out.rintln("测试foo方法有没有被调用");
turn"";
}ubcstaticvoidmain(Sing[]args){
Testobj=nl;
System.out.rintln(foo());
}
}鸣谢
说句实在话,这62道Java核心面试题在面试的过程中还是很常见的,值得好好复习一遍。
好了,我亲爱的小伙伴们,能看到这里绝逼是最优秀的程序员,二哥必须伸出帅气的大拇指为你点个赞!我是沉默王二,一枚有颜值却靠才华苟且的程序员。关注即可提升学习效率,别忘了三连啊,点赞、收藏、留言,我不挑,奥利给。
注:如果文章有任何问题,欢迎毫不留情地指正。