【面试高频问题总结】Java

Java基础知识

hashCode和equals和==相关问题

1. equals和==的区别

  • ==既可以比较基本数据类型,也可以比较引用数据类型,equals只能比较引用数据类型
  • ==比较基本数据类型,比较的是值;
  • ==比较引用数据类型,比较的是它们的地址值,即是否指向同一内存空间
  • equals比较引用数据类型,默认实现是return this == obj,默认比较两个对象的地址值;
  • 改写了的equals方法比较的是两个对象中的值是否相等
hashcode和equals相关规定
  • 两个对象相等,hashcode一定相同
  • 两个对象hashcode相同,它们不一定相同
  • 两个对象相等,equals方法返回true

2. 为什么重写了equals方法一定要重写hashcode方法?只重写equals方法不重写hashcode方***发生什么情况?

首先说这俩是啥:

equals方法是Object类中的一个方法,用来比较两个对象是否相等
hashcode方法是本地方法,是集合中用来判断两个元素是否相等的关键

其次明确,为什么要重写equals方法?

equals方法默认实现是比较两个对象的地址值,重写后equals方法比较的是两个对象的值,也就是两个内存地址中存储的值是否相等。为了比较两个对象的值是否相等,我们重写equals方法

那又为什么必须要重写hashcode方法呢?

重写了hashcode方法,才能鉴别两个值相同但内存地址不同的对象。
重写了hashcode方法,这两个对象的hashcode值才会相同
如果只重写equals方法不重写hashcode方法,就会发生两个值相同的对象equals返回true,但是hashcode值不同的情况


方法重写和方法重载的区别?

重写override:

在子类中,子类重写父类的同名方法。
要求返回值类型一样,方法名一样,参数列表一样。子类的访问权限不能比父类的小。(子类为public,父类private,推荐一样)

方法重写的应用场景:

当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,父类方法中的行为相当于默认动作。这样,即沿袭了父类的功能,又定义了子类特有的内容。
重写时,假如父类的方法有300行,在子类中重写此方法时不需要重写这300行代码;只写不一样的即可,相同的300行用super.call()调用

方法重写的注意事项

a.父类中私有方法不能被重写
子类只能继承父类非私有的成员变量和成员方法
既然没有继承,就谈不上重写了。
可以在子类中写一个一模一样的方法,但这个方法不是继承父类的,所以也不可能是重写得到的​
b.子类重写父类方法时,访问权限不能更低,推荐和父类的访问权限一致。(除非在业务确实需要将子类权限扩充)。
c.父类静态方法,子类也必须通过静态方法进行重写。

class Phone {
//提供打电话的基本功能
public void call(String name) {
System.out.println("打电话给" + name);
}
}
/*
研发了一款新手机:
打电话功能:打了电话之后,会播放音乐
*/
class NewPhone extends Phone {

// 对打电话功能进行了一些扩展
public void call(String name) {
// System.out.println("打电话给" + name);
super.call(name);
System.out.println("播放西游记主题曲");
}
}
class ExtendsDemo6 {
public static void main(String[] args) {
NewPhone newPhone = new NewPhone();
newPhone.call("刘亦菲");
}
}

重载overload:

在同一个类中,方法名一样,但是参数列表不一样。与返回值类型无关
如果在子类中定义了一个和父类同名的方法,但是参数列表不一样就会构成重载。
如果在子类中定义了一个和父类同名的方法,但是参数列表一样,但是返回值类型不一样,会报错。


final关键字的用法?

  1. 修饰类,该类不能被继承
  2. 修饰方法,该方法不能被改写
  3. 修饰变量
     (1)修饰的是基本数据类型,则该变量的值不能被改变
     (2)修饰的是引用数据类型,该引用数据只能指向同一个对象,对象的内容可以修改,但该引用型数据不可以指向其他对象

String、StringBuffer和StringBuilder的用法和区别?

三者区别

String 类型和 StringBuffer 的主要性能区别:String 是不可变的对象, 因此在每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,性能就会降低。

使用策略

(1)基本原则:
如果要操作少量的数据,用String ;
单线程操作大量数据,用StringBuilder ;
多线程操作大量数据,用StringBuffer。

(2)不要使用String类的"+"来进行频繁的拼接,产生很多新的string对象,性能极差,应该使用StringBuffer或StringBuilder类,这在Java的优化上是一条比较重要的原则。例如:

String result = "";
for (String s : hugeArray) {
    result = result + s;        //每次循环都会创建一个String result用于保存结果
}

// 使用StringBuilder
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
    sb.append(s);            //在原有的stringbuffer对象上操作,不产生新的对象
}
String result = sb.toString();

(3)为了获得更好的性能,在构造 StringBuffer 或 StringBuilder 时应尽可能指定它们的容量。当然,如果你操作的字符串长度(length)不超过 16 个字符就不用了,当不指定容量(capacity)时默认构造一个容量为16的对象。不指定容量会显著降低性能。

(4)总之,因为stringbuilder的线程不安全问题,一般多使用stringbuffer

======================================================================================

OOP面向对象编程

抽象类和接口两者区别在哪?

从成员、关系、设计理念三个方面回答

A:成员区别

抽象类:有成员变量,有抽象方法
接口:可以有抽象方法;只能有静态常量(默认用public static final修饰)

B:关系区别:

类与类:单继承
类与接口:多实现
接口与接口:多继承

C:设计理念不同

抽象类:和它的子类之间表现的是 is a的关系, 描述的是子类中的共性
接口:和它的子类之间表现的是** like a **的关系,描述的是子类特有的功能

抽象类和接口都不可以实例化对象,但是抽象类有构造方法,why?

抽象类的作用就是给子类来继承的,所以当子类需要实例化对象的时候,就会调用其父类的构造方法,对父类的成员变量进行初始化,所以抽象类需要有构造方法
接口中只有静态常量(一般用public static final修饰),也不可以让其他类继承,所以不需要有构造方法
抽象类中不写构造方法的特殊情况:抽象类可以继承具体类,抽象类中没有新的成员变量,就可以不写构造方法

全部评论

相关推荐

06-15 20:57
已编辑
门头沟学院 Java
CARLJOSEPH...:年轻人有傲气很正常,但是建议工作前洗净傲气。 说实在的,什么奖学金什么奖项的都很一般。尊重你的老师,在有时间的时候去上课,真遇到走不开的事,请态度端正地向你的老师说明情况,请求请假。我相信任何一个有师德的老师都会允许的(我的老师就是这样)。
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务