美文网首页Java 杂谈程序员互联网科技
史上最全Java面试题之相关概念篇!(带全部答案)

史上最全Java面试题之相关概念篇!(带全部答案)

作者: Java_老男孩 | 来源:发表于2019-03-07 20:22 被阅读50次

    面向对象的三个特征

    封装,继承,多态,这个应该是人人皆知,有时候也会加上抽象。

    多态的好处

    允许不同类对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用)。主要有以下优点:

    1.可替换性:多态对已存在代码具有可替换性

    2.可扩充性:增加新的子类不影响已经存在的类结构

    3.接口性:多态是超类通过方法签名,向子类提供一个公共接口,由子类来完善或者重写它来实现的。

    4.灵活性

    5.简化性

    代码中如何实现多态

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

    1. 接口实现

    2. 继承父类重写方法

    3. 同一类中进行方法重载

    虚拟机是如何实现多态的

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

    接口的意义

    接口的意义用三个词就可以概括:规范,扩展,回调。

    抽象类的意义

    抽象类的意义可以用三句话来概括:

    为其他子类提供一个公共的类型

    封装子类中重复定义的内容

    定义抽象方法,子类虽然有不同的实现,但是定义时一致的

    接口和抽象类的区别

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

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

    什么是不可变对象

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

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

    静态变量存储在方法区,属于类所有。实例变量存储在堆当中,其引用存在当前线程栈。

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

    当然可以创建一个包含可变对象的不可变对象的,你只需要谨慎一点,不要共享可变对象的引用就可以了,如果需要变化时,就返回原对象的一个拷贝。最常见的例子就是对象中包含一个日期对象的引用。

    java 创建对象的几种方式

    采用new

    通过反射

    采用clone

    通过序列化机制

    前2者都需要显式地调用构造方法。造成耦合性最高的恰好是第一种,因此你发现无论什么框架,只要涉及到解耦必先减少new的使用。

    switch中能否使用string做参数

    在idk 1.7之前,switch只能支持byte, short, char, int或者其对应的封装类以及Enum类型。从idk 1.7之后switch开始支持String。

    switch能否作用在byte, long上?

    可以用在byte上,但是不能用在long上。

    String s1=”ab”, String s2=”a”+”b”, String s3=”a”, String s4=”b”, s5=s3+s4请问s5==s2返回什么?

    返回false。在编译过程中,编译器会将s2直接优化为”ab”,会将其放置在常量池当中,s5则是被创建在堆区,相当于s5=new String(“ab”);

    你对String对象的intern()熟悉么?

    intern()方法会首先从常量池中查找是否存在该常量值,如果常量池中不存在则现在常量池中创建,如果已经存在则直接返回。

    比如

    String s1=”aa”;

    String s2=s1.intern();

    System.out.print(s1==s2);//返回true

    Object中有哪些公共方法?

    equals()

    clone()

    getClass()

    notify(),notifyAll(),wait()

    toString

    java当中的四种引用

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

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

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

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

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

    WeakReference与SoftReference的区别?

    这点在四种引用类型中已经做了解释,这里简单说明一下即可:

    虽然 WeakReference 与 SoftReference 都有利于提高 GC 和 内存的效率,但是 WeakReference ,一旦失去最后一个强引用,就会被 GC 回收,而软引用虽然不能阻止被回收,但是可以延迟到 JVM 内存不足的时候。

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

    不像C语言,我们可以控制内存的申请和释放,在Java中有时候我们需要适当的控制对象被回收的时机,因此就诞生了不同的引用类型,可以说不同的引用类型实则是对GC回收时机不可控的妥协。有以下几个使用场景可以充分的说明:

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

    通过软引用实现Java对象的高速缓存:比如我们创建了一Person的类,如果每次需要查询一个人的信息,哪怕是几秒中之前刚刚查询过的,都要重新构建一个实例,这将引起大量Person对象的消耗,并且由于这些对象的生命周期相对较短,会引起多次GC影响性能。此时,通过软引用和 HashMap 的结合可以构建高速缓存,提供性能。

    java中==和eqauls()的区别,equals()和`hashcode的区别

    ==是运算符,用于比较两个变量是否相等,而equals是Object类的方法,用于比较两个对象是否相等。默认Object类的equals方法是比较两个对象的地址,此时和==的结果一样。换句话说:基本类型比较用==,比较的是他们的值。默认下,对象用==比较时,比较的是内存地址,如果需要比较对象内容,需要重写equal方法。

    equals()和hashcode()的联系

    hashCode()是Object类的一个方法,返回一个哈希值。如果两个对象根据equal()方法比较相等,那么调用这两个对象中任意一个对象的hashCode()方法必须产生相同的哈希值。

    如果两个对象根据eqaul()方法比较不相等,那么产生的哈希值不一定相等(碰撞的情况下还是会相等的。)

    a.hashCode()有什么用?与a.equals(b)有什么关系

    hashCode() 方法是相应对象整型的 hash 值。它常用于基于 hash 的集合类,如 Hashtable、HashMap、LinkedHashMap等等。它与 equals() 方法关系特别紧密。根据 Java 规范,使用 equal() 方法来判断两个相等的对象,必须具有相同的 hashcode。

    将对象放入到集合中时,首先判断要放入对象的hashcode是否已经在集合中存在,不存在则直接放入集合。如果hashcode相等,然后通过equal()方法判断要放入对象与集合中的任意对象是否相等:如果equal()判断不相等,直接将该元素放入集合中,否则不放入。

    有没有可能两个不相等的对象有相同的hashcode

    有可能,两个不相等的对象可能会有相同的 hashcode 值,这就是为什么在 hashmap 中会有冲突。如果两个对象相等,必须有相同的hashcode 值,反之不成立。

    可以在hashcode中使用随机数字吗?

    不行,因为同一对象的 hashcode 值必须是相同的

    a==b与a.equals(b)有什么区别

    如果a 和b 都是对象,则 a==b 是比较两个对象的引用,只有当 a 和 b 指向的是堆中的同一个对象才会返回 true,而 a.equals(b) 是进行逻辑比较,所以通常需要重写该方法来提供逻辑一致性的比较。例如,String 类重写 equals() 方法,所以可以用于两个不同对象,但是包含的字母相同的比较。

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

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

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

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

    byte a = 127;

    byte b = 127;

    b = a + b; // error : cannot convert from int to byte

    b += a; // ok

    (译者注:这个地方应该表述的有误,其实无论 a+b 的值为多少,编译器都会报错,因为 a+b 操作会将 a、b 提升为 int 类型,所以将 int 类型赋值给 byte 就会编译出错)

    short s1= 1; s1 = s1 + 1; 该段代码是否有错,有的话怎么改?

    有错误,short类型在进行运算时会自动提升为int类型,也就是说s1+1的运算结果是int类型。

    short s1= 1; s1 += 1; 该段代码是否有错,有的话怎么改?

    +=操作符会自动对右边的表达式结果强转匹配左边的数据类型,所以没错。

    & 和 &&的区别

    首先记住&是位操作,而&&是逻辑运算符。另外需要记住逻辑运算符具有短路特性,而&不具备短路特性。

    public class Test{

    static String name;

    public static void main(String[] args){

    if(name!=null&userName.equals("")){

              System.out.println("ok");

          }else{

              System.out.println("erro");

          }

      }

    }

    以上代码将会抛出空指针异常。

    一个java文件内部可以有类?(非内部类)

    只能有一个public公共类,但是可以有多个default修饰的类。

    如何正确的退出多层嵌套循环?

    使用标号和break;

    通过在外层循环中添加标识符

    内部类的作用

    内部类可以有多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立.在单个外围类当中,可以让多个内部类以不同的方式实现同一接口,或者继承同一个类.创建内部类对象的时刻不依赖于外部类对象的创建。内部类并没有令人疑惑的”is-a”管系,它就像是一个独立的实体。

    内部类提供了更好的封装,除了该外围类,其他类都不能访问。

    final, finalize和finally的不同之处

    final 是一个修饰符,可以修饰变量、方法和类。如果 final 修饰变量,意味着该变量的值在初始化后不能被改变。finalize 方法是在对象被回收之前调用的方法,给对象自己最后一个复活的机会,但是什么时候调用 finalize 没有保证。finally 是一个关键字,与 try 和 catch 一起用于异常的处理。finally 块一定会被执行,无论在 try 块中是否有发生异常。

    clone()是哪个类的方法?

    java.lang.Cloneable 是一个标示性接口,不包含任何方法,clone 方法在 object 类中定义。并且需要知道 clone() 方法是一个本地方法,这意味着它是由 c 或 c++ 或 其他本地语言实现的。

    深拷贝和浅拷贝的区别是什么?

    浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。

    深拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

    static都有哪些用法?

    几乎所有的人都知道static关键字这两个基本的用法:静态变量和静态方法。也就是被static所修饰的变量/方法都属于类的静态资源,类实例所共享。

    除了静态变量和静态方法之外,static也用于静态块,多用于初始化操作:

    public calss PreCache{

    static{

            //执行相关操作

      }

    }

    此外static也多用于修饰内部类,此时称之为静态内部类。

    最后一种用法就是静态导包,即import static.import static是在JDK 1.5之后引入的新特性,可以用来指定导入某个类中的静态资源,并且不需要使用类名。资源名,可以直接使用资源名,比如:

    import static java.lang.Math.*;

    public class Test{

    public static void main(String[] args){

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

          System.out.println(sin(20));

      }

    }

    final有哪些用法

    final也是很多面试喜欢问的地方,能回答下以下三点就不错了:

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

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

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

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

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

    回答出编译器对final域要遵守的两个重排序规则更好:

    1.在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。

    2.初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。

    相关文章

      网友评论

        本文标题:史上最全Java面试题之相关概念篇!(带全部答案)

        本文链接:https://www.haomeiwen.com/subject/drjhpqtx.html