Java面经

文章目录

面试考点导图

在这里插入图片描述

JavaSE

Java和PHP的区别

  • 编程范式。Java是纯面向对象的语言。PHP既使用可面向对象的方式编程,又可使用面向过程的方式。
  • 语言类型。Java是编译型强类型的语言,变量必须声明类型。PHP是解释型弱类型的语言,变量不必声明类型。
  • PHP内置模板引擎,自身就是模板语言,而Java Web需要使用JSP容器如Tomcat或第三方模板引擎。
  • 多线程模式下,PHP开发者不需要写代码参与进程和线程的管理,这些都由PHP-FPM/HHVM/Apache实现。Java多线程编程需要Java开发者编码参与。PHP一个worker进程崩溃,master进程会自动新建一个新的worker进程,并不会导致PHP服务崩溃,而Java多线程稍有不慎(比如没有捕获异常)就会导致JVM崩溃退出。

Java中是如何支持正则表达式操作的

https://blog.csdn.net/YXX0529/article/details/105344621

  • Pattern类。pattern对象是一个正则表达式的编译表示
  • Matcher类。Matcher对象是对输入字符串进行解释和匹配操作的引擎

Java中的String类提供了支持正则表达式操作的方法,包括:matches()、replaceAll()、replaceFirst()、spilt()。此外,Java中可以用Pattern类表示正则表达式对象,它提供了丰富的API进行各种表达式的操作,如:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
class RegExpTest {
    public static void main(String[] args) {
        String str = "成都市(成华区)(武侯区)(高新区)";
        Pattern p = Pattern.compile(".*?(?=\\()");
        Matcher m = p.matcher(str);
        if(m.find()) {
            System.out.println(m.group());
        }
    }
}

简单描述一下正则表达式及用途

在编写处理字符串的程序时,经常会有查找符合某些复杂规则字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。计算机处理的信息更多的时候不是数值,而是字符串,正则表达式就是在进行字符串匹配和处理的时候成为最为强大的工具,绝大多数语言都提供了对正则表达式的支持。

比较一下Java和JavaScript

是两种不同的产品。Java是面向对象的程序设计语言,特别适合互联网应用程序开发,而JavaScript是为了扩展Netscape浏览器的功能而开发的一种可以嵌入Web页面中运行的基于对象和事件驱动的解释性语言。

  • 基于对象和面向对象:Java是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象;JavaScript是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。它是一种基于对象和时间驱动的编程语言,因而它本身提供了非常丰富的内部对象供设计人员使用。
  • 解释和编译:Java的源代码在执行之前,必须经过编译。JavaScript是一种解释型编程语言,其源代码不需经过编译,由浏览器解释执行。(目前的浏览器几乎都使用了JIT技术来提升JavaScript的运行效率)
  • 强类型变量和弱类型变量:Java采用强类型变量检查,即所有变量在编译之前必须作声明;JavaScript中变量是弱类型的,甚至在使用变量前可以不作声明,JavaScript的解释器在运行时检查推断其数据类型。
  • 代码格式不一样。

在Java中如何跳出当前的多重嵌套循环

  • 使用一个标记变量,然后在每一层循环中检查这个变量,如果设置为true,则跳出每层循环。
    在这里插入图片描述
  • 通过异常捕获的方式跳出多层循环,在想要跳出的位置抛出一个异常,然后用catch捕获该异常。
    在这里插入图片描述
  • 使用带标签的break语句跳出循环,在循环前设置一个标签变量,然后在需要跳出的循环处使用break标签变量,从而跳到了标签定义的位置。
    在这里插入图片描述

&和&&的区别

  • &和&&都可以用作逻辑与的运算符,表示逻辑与,当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则只要有一方为false,结果为false。
  • &&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式,例如在验证用户登录时判定用户名不是null且不是空字符串,应当写为:username != null && !username.equals(""),二者的顺序不能交换,更不能用&运算符,因为第一个条件如果不成立,根本不能进行字符串的equals比较,否则会产生NullPointerException异常。
int i=1;
if(i==2 & i++==2){} //i==2为false,但i++==2还会继续比较,所以i++被执行
System.out.println(i);//i 打印出来为2
int j=1;
if(j==2 && j++==2){} //j==2为false,但j++==2不会继续比较,所以j++不被执行
System.out.println(j);//j打印出来为1
  • &还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&进行按位与操作。

int和Integer的区别

为了将基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的封装类。

  • 原始类型:boolean,char,byte,short,int,long,float,double
  • 封装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

两者区别:

  • 数据类型:int是基本数据类型,Integer是int包装类,可以有方法和属性,利用这些方法和属性处理数据,但是用final修饰,属性不可变、方法不可覆盖、类不可继承。
  • 传递方式:int在传递参数时都是按值传递。Integer按引用传递,传递的是对象地址。
  • 默认值:int默认是0,Integer默认是null。
  • 存储位置:基本类型在内存中是存储在栈中,好处是速度快(不涉及对象的构造和回收),而实际的Integer对象是存在堆中,目的主要是更好的处理数据之间的转换。
  • ==比较:对于基本类型,==操作符比较的是两个变量的值是否相等;对于引用类型变量,==操作符比较的是两个引用是否指向同一个对象。

我们在web应用开发过程中经常遇到输出某种编码的字符串,如iso8859-1等,请你讲讲如何输出一个某种编码的字符串

Public String translate (String str) {
String tempStr = “”;
try {
tempStr = new String(str.getBytes(“ISO-8859-1), “GBK”);
tempStr = tempStr.trim();
}
catch (Exception e) {
System.err.println(e.getMessage());
}
return tempStr;
}

String,StringBuilder和StringBuffer的区别

  • String:不可变字符序列
  • StringBuilder:可变字符序列,效率高,线程不安全
  • StringBuffer:可变字符序列,效率低,线程安全

String是最基本的数据类型吗?

不是,是引用数据类型。基本数据类型是分配在栈上的,引用数据类型是分配在堆上的。

请你谈谈大O符号(big-O notation)并给出不同数据结构的例子

大O描述当数据结构中的元素增加时,算法的规模和性能在最坏情景下有多好。
我们一般用大O符号基于时间、内存、性能选择最好的实现。
大O符号表示一个程序运行时所需要的渐进时间复杂度上界。

请你讲讲数组(Array)和列表(ArrayList)的区别?什么时候应该使用Array而不是ArrayList?

在这里插入图片描述

  • 存储内容:Array数组可以包含基本类型和对象类型,ArrayList只能包含对象类型。
  • 空间大小:Array大小是固定的,ArrayList大小是动态变化的。
  • 方法:ArrayList方法上比Array更多样化,比如:addAll(),removeAll(),iterator()等。
    所需的数据结构是定长时用Array,不定长用ArrayList。
    对于基本类型数据,集合使用自动装箱来减少编码工作量,但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。

什么是值传递和引用传递

  • 值传递是针对基本类型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。
  • 引用传递是针对对象类型而言的,传递的是该变量的内存地址,而不是对象本身,所以对引用对象的操作会改变原对象。(Object,二维数组,List,Map)

Java支持的数据类型有哪些,什么是自动拆装箱?

byte、short、int、long、float、double、boolean、char
自动装箱是Java编译器在基本数据类型和对应的对象包装类型之间做的转化,例如,int转为Integer、byte转为Byte,反之则是自动拆箱。

请你解释为何会出现4.0 - 3.6 = 0.40000001这个现象?

浮点数值采用二进制来表示,而二进制无法精确地表示十进制小数,计算时需要将十进制小数转化为二进制进行计算,转换过程出现了误差。

一个十进制的数在内存中是怎么存的?

以补码形式存储。
正数原反补码相同,负数反码是将原码除符号位其余位取反,补码是将反码加1。

Lambda表达式的优缺点

Lambda 闭包 将函数作为参数传递进方法里。

  • 优点:1.简介 2.非常容易并行计算 3.可能成为未来编程趋势
  • 缺点:1.若不用并行计算,很多时候计算速度不如for循环(并行计算有时需要预热才显示出计算效率) 2.不容易调试 3.如果其它程序员没有学过,可能不易理解

Java8新特性

Lambda表达式-Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法
中)。
默认方法− 默认方法就是一个在接口里面有了一个实现的方法。

新工具− 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。

Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。

Date Time API − 加强对日期与时间的处理。

Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用

请你说明符号“==”比较的是什么?

“ == ”对比两个对象的内存引用,如果两个对象的引用完全相同(指向同一个对象)时,“ == ”操作将返回true,否则返回false,“ == ”如果两边是基本类型,就是比较数值是否相等。

Object若不重写hashCode()的话,hashCode()如何计算出来?

Object的hashcode方法是本地方法,也就是用C语言或C++实现的,该方法直接返回对象的内存地址。

为什么重写equals还要重写hashcode?

HashMap中比较key时先求出key的hashcode(),比较其值是否相等,若相等再比较equals(),若equals()相等则相等,不相等则不相等。Object的equals默认是比较内存地址,hashcode默认是内存地址的哈希值,如果equals重写了,比较结果为true时,如果不重写hashcode,那么他会默认用object的hashcode方法,所以他们的hashcode值是不一样的,这样就导致两个对象的equals相等而hashcode不相等,很据hashcode规则,两个对象equals相等,hashcode一定相等,产生矛盾,所以重写equals一定要重写hashcode。

介绍一下map的分类和常见的情况

Java为数据结构中的映射定义了一个接口java.util.Map,它有四个实现类,分别是HashMap,Hashtable,LinkedHashMap和TreeMap。
HashMap是一个最常用的Map,它根据键的hashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为NULL,允许多条记录的值为NULL。HashMap不支持线程的同步,即同一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致,如果需要同步,可以用Collections的synchronizedMap方法使HashMap具有同步的能力。
Hashtable与HashMap类似,它继承自Dictionary类,不同的是:它不允许记录的键或者值为空;它支持线程同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtable在写入时会比较慢。
LinkedHashMap保存了记录的插入顺序,再用Iterator遍历LinkedHashMap时,先得到的纪录一定是先插入的。
TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当Iterator遍历TreeMap时,得到的记录是排过序的。

Java里面的final关键字是怎么用的?

Java中,final关键字可以用来修饰类、方法和变量(包括成员变量和全局变量)。

  • 修饰类
    当用final修饰一个类时,表明这个类不能被继承。也就是说,如果一个类你永远不会让他被继承,就可以用final进行修饰。final类中的成员变量可以根据需要设为final,但是要注意final类中的所有成员方法都会被隐式地指定为final方法。
  • 修饰方法
    只有想明确禁止该方法在子类中被覆盖的情况下才将方法设置为final的,即父类的final方法不能被子类覆盖。
  • 修饰变量
    当final修饰一个基本数据类型时,表示该基本数据类型的值一旦在初始化后便不能发生变化;如果final修饰一个引用类型时,则在对其初始化后便不能再让其指向其他对象了,但该引用所指向的对象的内容是可以发生变化的。

谈谈关于Synchronized和lock

在这里插入图片描述

  • synchronized是关键字,内置语言实现,lock是一个接口。
  • synchronized在线程发生异常时会自动释放锁,因此不会发生异常死锁,lock异常时不会自动释放锁,所以需要在finally中释放锁。
  • lock是可以中断锁,synchronized是非中断锁,必须等待线程执行完成释放锁。
  • 通过lock可以知道有没有成功获取锁,而synchronized无法办到
  • lock可以读共享,使用读锁提高读效率。

请介绍一下volatile

volatile关键字是用来保证有序性和可见性的。
原子性:一个或多个操作,要么全部执行且执行过程中不会被任何因素打断,要么就都不执行。
可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看到修改的值。
有序性:程序执行的顺序按照代码的先后顺序执行。
一旦一个共享变量被volatile修饰之后,就具备了两层语义:

  • 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这个新值对其他变量是立即可见的。(Java内存模型分为:主内存、工作内存,使用volatile关键字会将修改的值立即写入主内存,当线程2修改时,会导致线程1工作内存中缓存变量的缓存行失效,然后线程1再次去主存中读取修改后的新值。)
  • 禁止进行指令重排序。(通过插入内存屏障来保证的)

介绍一个Synchronized锁,如果用这个关键字修饰一个静态方法,锁住了什么,如果修饰成员方法,锁住了什么?

修饰对象:

  • 修饰一个类,其作用范围是synchronized后面的括号括起来的部分,作用的对象是这个类的所有对象。
  • 修饰一个方法,被修饰的方法称为同步方法,其作用范围是整个方法,作用的对象是调用这个方法的对象。
  • 修饰一个静态方法,其作用范围是整个静态方法,作用的对象是这个类的所有对象。
  • 修饰一个代码块,其修饰的代码块称为同步语句块,其作用范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象。

若对一个类不重写,它的equals()方法是如何比较的?

比较的是对象的地址。

请解释hashCode()和equals()方法有什么联系?

  • 相等(相同)的对象必须具有相等的哈希码(或者散列码)
  • 如果两个对象的hashCode相同,他们不一定相同

请解释Java中的概念,什么是构造函数?什么是构造函数重载?什么是复制构造函数?

构造函数是一种特殊的方法,主要用来在创建对象时初始化对象,为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中,一个类可以有多个构造函数,可根据其参数个数的不同或参数类型的不同区分它们,即构造函数的重载,
Java不支持复制构造函数,如果不是自己写的构造函数的情况下,java不会创建默认的复制构造函数。

请说明Java中的方法重写(Overriding)和方法重载(Overloading)是什么意思?

在这里插入图片描述
重载和重写是Java多态性的体现。

  • 方法重载是一个类中定义了多个方法名相同,但他们的参数数量不同或者数量相同,参数类型和次序不同。
  • 方法重写是在子类存在方法与父类的方法名字相同,而且参数的个数和类型一昂,返回值也一样的方法。
    在这里插入图片描述

Query接口的list方法和iterate方法有什么区别?

  • 返回的类型不同,list()返回List,iterate()返回Iterator
  • 获取的方式不同,list会一次性将数据库中的信息全部查询出,iterator会先把所有数据的id查询出来,然后真正要遍历某个对象的时候先到缓存中查找,如果找不到,以id为条件再发送一条sql到数据库,这样如果缓存中没有数据,则查询数据库的次数为N+1
  • iterate会查询2级缓存,list只会缓存,但不会使用缓存,除非结合查询缓存。
  • list中返回的List中每个对象是完整的,iterate中返回的对象仅包含主键值只有你对iterator的对象进行操作时,Hibernate才会向数据库再次发送SQL语句来获取给对象的属性值。

请你谈一下面向对象的“六原则一法则”

  • 单一职责原则:一个类只做它该做的事情。
  • 开闭原则:软件实体应该对扩展开放,对修改关闭。
  • 依赖倒转原则:面向接口编程。程序要依赖于抽象接口,而不依赖于具体实现。
  • 里氏替换原则:任何时候都可以用子类型替换掉父类型。
  • 接口隔离原则:接口要小而专,绝不能大而全。
  • 聚合复用原则:优先使用聚合关系复用代码
  • 迪米特法则:最少知识原则,一个对象应当对其他对象有尽可能少的了解。

请说明如何通过反射获取和设置对象私有字段的值?

可以通过类对象的getDeclaredField()方法字段(Field)对象,然后再通过字段对象setAccessible(true)将其设置为可以访问,接下来就可以通过get/set方法来获取/设置字段的值。

           private String phoneNum;
           f = stuClass.getDeclaredField("phoneNum");  
           f.setAccessible(true);//暴力反射,解除私有限定 

重载和重写的区别。重载的方法能否根据返回类型进行区分?

方法的重载和重写都是实现多态的方式,区别在于,重载实现的是编译时的多态性,重写实现的是运行时的多态性。
重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载。
重写发生在子类与父类之间,重写要求子类被重写方法与父类有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏替换原则)。
重载的方法不能根据返回类型进行区分。编译器通过各个方法给出的参数类型与特定的方法调用所使用的值类型进行区分。

请判断,两个对象值相同(x.equals(y) == true),但却可有不同的hashcode,是否正确,为什么?

如果只重写了equals()方法,没有重写hashcode()方法会出现这种情况,但是是不对的。
Java规定:

  • 如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;
  • 如果两个对象的hashCode相同,他们不一定相同。

请说明内部类可以引用它包含类的成员吗,如果可以,有什么限制吗?

如果不是静态内部类,完全可以,没有什么限制。
在静态内部类下,不可以访问外部类的普通成员变量,只能访问外部类的静态成员。

内部类分两种:

  • 非静态内部类
    • 非静态方法
      • 可以访问包含类的成员变量
        • 静态成员变量,包括public,protected,private
        • 非静态成员变量,包括public,protected,private
    • 静态方法(非静态内部类不能有静态方法)
    • 必须依附外部类,也就是只有实例化包含类后,再用特殊语法才能实例化内部类
  • 静态内部类
    • 非静态方法
      • 包含类非静态成员:不能访问
      • 包含类静态成员:可以访问
    • 静态方法
      • 包含类的非静态成员:不能访问
      • 包含类的静态成员:可以访问

请说明Java语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?

Java通过面向对象的方法进行异常处理,把各种不同的异常分类,并提供了良好的接口,在Java中,每个异常都是一个对象,它是Throwable类或其它子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含异常信息,调用这个对象的方法就可以捕捉到这个异常并进行处理。

  • try块表示程序正常的业务执行代码,如果程序在执行try块的代码出现了“非预期”情况,JVM将会生成一个异常对象,这个异常对象会被后面相应的catch块捕捉
  • catch块表示一个异常捕捉块,当程序执行try块引发异常时,这个异常对象将会被后面相应的catch块捕捉。
  • throw用于抛出一个异常对象。throw后面需要一个异常对象
  • throws用于在方法签名中声明抛出一个或多个异常类,throws关键字后可以紧跟一个或多个异常类
  • finally块代表异常处理流程中总会执行的代码块

try块中可以抛出异常

throw和throws区别:

  • throw用来抛出一个具体的异常,throws是用来声明一个方法可能会抛出的所有异常类型
  • 语法
    • throw (异常对象)throw e;
    • 方法名 (参数)throws 异常类1,异常类2
      public void doA(int a)throws Exception1, Exception2{…}

请说明Java的接口和C++的虚类的相同和不同处

c++的虚类和Java的抽象方法相同,其与接口的不同之处在于:

  • 只能继承一个虚类,可以实现多个接口
  • 虚类中可以有构造方法,接口没有构造方法
  • 虚类中可以有非抽象方法,接口中必须都是抽象方法
  • 虚类的访问权限可以为public,private,protected,default,接口的访问权限只能是public
  • 虚类中的方法可以是public,private,protected,default,但接口的方法只能是是public和default

相同之处在于:都不能被实例化

请判断当一个对象被当做参数传递给一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

是值传递,Java只有值传递,当一个对象实例作为一个参数被传递到方法中时, 参数的值就是该对象的也引用一个副本,指向同一个对象,对象的内容可以在被调用的方法中改变,但是对象的引用是永远不会变的。

请你说说静态内部(嵌套)类和内部类的不同

  • 内部类是定义在类中的类,它的创建依赖一个外部类对象作为宿主,内部类必须寄生在外部类对象中才能创建实例。
Outer outer = new Outer();
Inner inner = outer.new Inner();
  • 静态:用来修饰类的内部成员(静态方法、静态成员变量、静态常量)唯一的作用是,跟随类的加载而产生,就可以用“类名+静态成员名”获得
  • 静态内部类:这个类没有必要单独存放一个文件夹,它一般只被外部类使用,可以直接用“外部类名+内部类名”获得。
  • 静态内部类内部,不能访问外部非静态成员。这是由Java语法“静态方法不能直接访问非静态成员”所限定。

请你讲讲abstract class和interface的区别

抽象类和接口中,都有抽象方法需要实现,他们都不能创建实例对象,区别是:

  • 抽象类可以有构造方法,普通成员变量,普通方法, 接口不行
  • 抽象类和接口都可以包含静态成员变量、静态方法,抽象类中的静态成员变量可以是任意访问类型,但是接口必须是public
  • 抽象类的抽象方法访问类型可以是public、protected,但接口必须是public
  • 一个类可以实现多个接口,但是只能继承一个抽象类

请说明Overload和Override的区别,Overloaded的方法是否可以改变返回值的类型?

方法重载和方法重写是多态性的两种体现方式,重写是父类与子类之间的多态性,重载是一个类中的多态性体现。
重载表示同一个类中可以有多个不同参数列表但是方法名相同的方法。
重写表示子类中有与父类同名且参数类型相同的某个方法。
重写:

  • 方法名、参数、返回值相同

  • 子类方法不能缩小父类方法的访问权限

  • 子类方法不能抛出比父类方法更多的异常(子类方法可以不抛出异常)

  • 存在于父类与子类之间

  • 方法被定义为final不能重写
    重载:‘

  • 参数个数、类型、顺序至少有一个不同

  • 不能重载只有返回值不同的方法名

  • 存在于一个类中

overloaded的方法可以改变返回值的类型

请说明final,finally,finalize的区别

  • final用于声明属性、方法和类,分别表示属性不可变,方法不可覆盖、类不可继承
  • finally是异常处理语句结构的一部分,表示总是执行
  • finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。

请说明面向对象的特征有哪些方面

  • 抽象
    抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处。
  • 封装
    封装是把描述一个对象的属性和行为的代码封装在一个模块中,也就是一个类中。“高内聚、低耦合”
  • 继承
    在定义和实现一个类时,可以在一个已经存在的类的基础上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承,提高了代码的可重用性和扩展性。
  • 多态
    多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行时才确定。同一事件发生在不同对象上会产生不同的结果。

请说明Comparable和Comparator接口的作用以及他们的区别

  • Java提供了只包含一个compareTo()方法的Comparable接口,这个方法可以给两个对象进行排序。具体来说,它返回负数,0,正数来表明输入对象小于,等于,大于已存在的对象
  • Java提供了包含compare()和equals()两个方法的Comparator接口。compare()方法用来给两个输入参数排序,返回负数,0,正数来表示第一个参数是小于,等于,大于第二个参数的。equals()方法需要一个对象作为参数,它用来决定输入参数是否和comparator相等,只有当输入参数也是一个comparator并且输入参数和当前comparator的排序结果是相同的时候,这个方法才返回true。

接口和抽象类的区别是什么

都不能创建实例对象

  • 抽象类用abstract关键字修饰,接口用interface关键字修饰
  • 抽象类可以有构造方法,普通成员变量,普通方法,接口没有
  • 抽象类和接口都可以包含静态成员变量和静态方法,但抽象类中的静态成员变量可以是任意访问类型,接口必须是public
  • 抽象类的抽象方法的访问类型可以是public、protected,但接口必须是public
  • 一个类可以实现多个接口,但只能继承一个抽象类

请说明Java是否支持多继承?

Java中类不支持多继承,只支持单继承(即一个类只有一个父类)。但是Java可以实现多个接口,接口的作用是用来扩展对象的功能,一个子接口继承多个父接口,说明子接口扩展了多个功能,当类实现接口时,类就扩展了相应的功能。

如何通过反射创建对象?

在这里插入图片描述

  • 通过类对象调用newInstance()方法,例如:String.class.newInstance()
  • 通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器对象并调用newInstance()方法创建对象,例如:String.class.getConstructor(String.class).newInstance(“Hello”)

是否可以在static环境中访问非static变量?

不可以。java类加载主要分为加载、验证、准备、解析、初始化,静态变量是在准备阶段进行初始化,非静态变量是在初始化阶段才初始化的。
非静态变量和方法的调用需要对象的存在,加载类是,静态代码块,方法优先加载,如果在这调用非静态的,但对象还没创建出来,会报错。

请解释一下extends和super泛型限定符

extends指定上界限,只能传入本类和子类,用来限制类型的上限
super指定下界限,只能传入本类和父类,用来限制类型的下限

什么是泛型

泛型是一种参数化类型,多用于容器中,往容器中放数据,事先约定什么类型数据,放的时候会检查,不是正确的数据类型会报错,这样可以建立安全数据,也避免了强制类型转换。

静态变量存在什么位置?

方法区

解释一下类加载机制,双亲委派模型,好处是什么?

类加载机制:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。

类加载时机:类的生命周期是从类被加载到虚拟机内存中,到卸载内存为止。

类的生命周期:加载 - 连接(验证 准备 解析) - 初始化 - 使用 - 卸载

类加载过程:

  • 加载
    • 从Class文件获取二进制字节流
    • 将字节流中的静态结构转化为方法区的运行时的动态结构
    • 从内存中生成代表该Class的java.lang.Class对象,作为方法区该类的访问入口
  • 连接
    • 验证:验证Class文件的字节流中包含的信息是否符合JVM的要求,并确保不会危害JVM自身的安全
    • 准备:为静态变量分配内存并赋初始值
    • 解析:将常量池内的符号引用转换为直接引用
  • 初始化
    调用了类的clinit()方法,为静态变量赋予实际的值,执行静态代码块

双亲委派模型:每次收到类加载请求时,现将请求委派给父类加载器,如果父类加载器无法完成加载,那么子类尝试自己加载

好处:在于Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,他存在在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的Bootstrap ClassLoader进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。(避免类的重复加载,也避免Java的核心API被篡改)

请你谈谈StringBuffer和StringBuilder有什么区别,底层实现上呢?

在这里插入图片描述
StringBuffer线程安全,StringBuilder线程不安全。两者都继承了AbstractStringBuilder,StringBuffer重写AbstractStringBuilder方法的时候用了同步块synchronized

String是否能被继承?

不能,String被final修饰

请说明“static”关键字是什么意思?Java中是否可以覆盖(重写)一个private或者是static的方法?

static关键字表明一个成员变量或者成员方法可以在类没有实例化的情况下被访问。
重写的前提是必须要继承,private修饰不支持继承,所以private方法不支持被重写。
静态方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,静态方法使编译时静态绑定的。

请说明重载和重写的区别,相同参数不同返回值能重载吗?

都是实现多态
重载:

  • 在同一个类中有多个名称相同的方法,参数列表各不同
  • 不能重载只有返回类型不用的方法

重写:

  • 发生在子类与父类之间
  • 子类中方法与父类的某一方法有相同的名称和参数列表、返回类型
  • 子类不能抛出比父类更多的异常
  • 子类被重写方法访问权限不能少于父类

请列举你知道的Object类的方法并简要说明

  • clone():创建并返回当前对象的一个副本
  • equals(Object obj):用于比较两个对象的地址是否相同,即两个引用是否指向同一个地址
  • getClass():用于返回当前运行时对象的Class对象,使用了final关键字,故不允许子类重写
  • toString():返回类的名字@实例的哈希码的16进制字符串
  • notify():唤醒等待队列中的其中一个进程
  • notifyAll():唤醒线程等待队列中的所有进程
  • wait():在其他线程调用此对象的notify()方法或notifyAll()方法前,导致进程等待
  • hashcode():返回该对象的哈希码值
  • finalize():用于释放资源,GC在回收对象之前调用此方法

请说明类和对象的区别

  • 类是对某一事物的描述,是抽象的,而对象是一个实实在在的个体,是类的一个实例
  • 类是对象的抽象,对象是类的实例
  • 对象是函数、变量的集合体,类是一组函数和变量的集合体,即类是一组具有相同属性的对象集合体

请解释一下String为什么不可变?

String是被final修饰的,String类源码中是一个value的字符数组,被private final修饰,所以不能变

请讲讲Java有哪些特性,并举一个和多态有关的例子

封装 继承 多态
多态:允许不同类的对象对同一消息做出 响应,即同一消息可以根据对象的不同而采取不同的行为方式。
方法重写重载都和多态有关

请你讲讲wait方法的底层原理

wait()和notify()方法或者notifyAll()方法一起搭配使用
wait方法会将当前线程放入waitset等待被唤醒

  • 将当前线程封装成objectwaiter对象node
  • 通过objectmonitor::addwaiter方法将node添加到_WaitSet列表中
  • 通过objectmonitor::exit方法释放当前的objectmonitor对象,这样其它竞争线程就可以获取该objectmonitor对象
  • 最终底层的park方法会挂起线程

notify方法就是随机唤醒等待池中的一个线程

请说明List、Map、Set三个接口存取元素时,各有什么特点?

在这里插入图片描述

  • List和Set存储的是单个数据,Map存储的是键值对
  • List中的数据是有序且重复的,Set中的数据是无序且不允许重复的
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值