【面试系列】Java面试知识篇(四)

发布于:2022-12-21 ⋅ 阅读:(158) ⋅ 点赞:(0)

在这里插入图片描述
个人简介:

📦个人主页:赵四司机
🏆学习方向:JAVA后端开发
📣种一棵树最好的时间是十年前,其次是现在!
🔔博主推荐网站:牛客网 刷题|面试|找工作神器
💖喜欢的话麻烦点点关注喔,你们的支持是我的最大动力。

前言

由于很快到了金九银十的秋招季节,博主最近也在找一些面经资源,但是发现很多都不全,后来我发现了牛客网这个网站,发现里面不仅可以看面经,还能刷题模拟面试,要是你要找各种招聘信息也可以在上面找到,我愿称之为程序员必备网站,下面把它推荐给你们!
链接地址:牛客网

在这里插入图片描述

36.面向对象三大特性

(1)封装

封装就是将对象的状态信息(属性)封装在自己内部,不允许外部对象直接访问对象内部信息,但是内部对象可以对外提供方法供外部对象访问。

(2)继承

不同的对象之间相互之间可能会有一些共同点,比如学生、教师都有人的属性,同时,每一个对象也会有自己得特殊属性,比如张三喜欢篮球,李四喜欢足球,王五喜欢地球。继承是使用已定义的类作为基础建立新的类的技术,新定义的类可以定义新的特性或者方法,也可以用父类的功能,但是不能选择性地继承父类。通过使用继承,可以快速创建新的类,可以提高代码重用性,程序可维护性,提高开发效率。

注意:

  • 子类拥有父类的属性和方法(包括私有属性和方法),但是私有属性和方法子类只是拥有并不能使用。
  • 子类可以拥有自己的新的属性或者方法
  • 子类可以用自己的方式实现父类的方法

(3)多态

  • 多态,表示一个对象具有多种形态,具体表现为父类引用指向子类对象。
  • 编译看左边,运行看右边:编译时候只能调用父类中的方法,而运行时候执行的是子类重写父类的方法。
  • 多态性前提:类的继承、方法重写。
  • 对象的多态性只适用于方法不适用于属性。

37.引用拷贝、浅拷贝、深拷贝

  • 浅拷贝:浅拷贝会在堆上创建一个新的对象(区别于引用拷贝的一点),不过,如果原对象内部的属性是引用类型的话,浅拷贝会直接复制内部对象的引用地址,也就是说拷贝对象和原对象共用同一个内部对象。
  • 深拷贝 :深拷贝会完全复制整个对象,包括这个对象所包含的内部对象。
    在这里插入图片描述

38.HashCode有什么作用

  • hashCode()的作用是获取哈希码,也称为散列码,这个散列码的作用是确定对象在哈希表的索引位置

  • HashCode()定义在JDK的Object类中,这就意味着任何对象都有hashCode()函数,另外需要注意的是Object的hashCode()方法是本地方法,也就是用C或C++实现的,该方法通常用来将对象内存地址转换成整数之后返回。

  • 散列表的存储方式是键值对方式,它的特点是能根据键快速检索出对应的值,这其中就利用了散列码。

  • 为什么要有hashCode:举个例子,当我们在存储hashSet时候,hashSet会先计算对象的hashCode值来判断对象加入的位置,若该位置为空则说明集合中没包含这个对象,可以直接加入;否则就会调用equals方法判断这个对象是否和该位置的对象相等,若相等则不进行插入,否则就会重新散列到其他位置,这样就大大减少了equals的次数,提高了执行效率。

  • hashCode和equals都是比较两个对象是否相等,那为什么要同时提供两个方法呢?因为当两个对象的hashCode相等时候这两个对象不一定就是相同的,这取决于你的哈希算法,越糟糕的哈希算法碰撞几率越大,所以必须还要提供equals方法做进一步判断。但是单单用equals方法也是不行的,这样会大大降低执行效率。

39.为什么重写equals方法时候还必须重写hashCode()方法

因为两个相等的对象它们的HashCode值一定是相等的,如果重写了equals方法hashCode方法没有重写的话就会导致equals判断两个对象相等但是两者hashCode值不相等的情况出现。

40.intern方法有什么作用

String.intern()方法是一个本地方法,其作用是将指定字符串对象的引用保存在字符串常量池中

  • 在JDK1.6中,当字符串调用intern时候,如果这时候字符串常量池先前就创建了这个字符串对象,则intern方法直接返回常量池中该字符串对象的引用。
  • 在JDK1.7中,当调用intern时候,如果这时候字符串常量池中存在该字符串对象,则Intern方法将常量池中该对象的引用。若这时候堆中已存在该字符串对象,则将堆中该对象的引用存入常量池,然后返回该引用;若堆中不存在该对象,则直接在字符串常量池中创建该字符串对象并返回。

例题:

public static void main(String[] args) {
    String s = new String("1");
    s.intern();
    String s2 = "1";
    System.out.println(s == s2);   //JDK1.6 false  JDK1.7 false

    String s3 = new String("1") + new String("1");
    s3.intern();
    String s4 = "11";
    System.out.println(s3 == s4);  //JDK1.6 false  JDK1.7 true
}

//执行s3 = new String的时候,s3指向堆区的"11",而常量池中是没有"11"对象的,这时候执行s3.intern在jdk1.6时候会将"11"字符串对象放入字符串常量池并返回(但不是返回给s3),此时s4="11"这时候字符串常量池中已有"11"字符串对象,直接返回该对象的引用。这时候s3和s4是不等的。
//在jdk1.7中,执行s3.intern时候,这时候堆中已存在"11"对象,这时候直接将堆中"11"对象的引用存入字符串常量池,当执行s4="11"时候,直接让s4指向常量池中的字符串对象引用,因此这时候s3和s4都是指向堆中的"11"对象。
public static void main(String[] args) {
    String s = new String("1");
    String s2 = "1";
    s.intern();
    System.out.println(s == s2);   //JDK1.6 false  JDK1.7 false

    String s3 = new String("1") + new String("1");
    String s4 = "11";
    s3.intern();
    System.out.println(s3 == s4);  //JDK1.6 false  JDK1.7 false
    //jdk1.6中s3指向堆中"11"对象,s4指向常量池中"11"对象;jdk1.7中也是如此,执行s3,intern时候,字符串常量池中已经存在"11"对象。
    //但是执行下面语句输出是true
    String s5 = s3.intern();
    Sout(s4 == s5);
    //这是因为字符串常量池中已经存在了"11",s5接收的就是字符串常量池中该对象的引用,而该对象就是s4创建的。
}
  • 在JDK1.6中,字符串常量池存在于堆的永久代,而永久代和正常的堆区是分开的,永久代是类静态区域,主要存储一些加载类的信息,常量池,方法片段等内容,默认大小只有4M。s2指向的对象存放在常量池,s指向的对象存放在堆区,拿一个堆区域的对象地址和一个永久代区域的对象地址比较显然是不等的,即使调用了intern方法。
  • 在JDK1.7中,字符串常量池从永久代移到了正常的堆区中,jdk8建立元空间抛弃了永久代。

温馨提示:上面只是我总结的面经知识,如果你想要更全面的可以到网站自行查看喔。
友情链接:牛客网
在这里插入图片描述