java面试基础题

这篇博客汇总了Java面试中常见的基础题目,涵盖了面向对象的四大特性、String与StringBuilder的区别、对象比较、异常处理、装箱拆箱、内部类、反射、重写与重载、抽象类与接口等多个核心知识点,帮助读者深入理解Java编程的基础概念。
摘要由CSDN通过智能技术生成


题目来自: 2019Android秋招提前批面试总结(已拿BAT等6家offer)

题目汇总

1.java面向对象编程的四大特性与含义

四大特性:抽象封装继承多态

抽象:可以理解为对事物的抽象,抽象就是将一类实体的共同特性抽象出来,封装在一个新的概念(类) 中,然后把不同特性作为抽象方法留给子类去实现。

封装将某事物的属性和特征封装到一个对象(类)中,在这个对象中将属性保护(private)起来,尽量隐藏一些内部的具体细节,只暴露一些方法给外界去使用

封装的步骤:
  1、修改属性的可见性来限制对属性的访问
  2、为每个属性创建赋值和取值的方法,用于对这些属性的访问
  3、在赋值和取值的方法中,加入对属性的存储限制
封装的好处:
  1、实现了专业的分工
  2、类内部的结构能够自由修改
  3、能够对成员进行更精确的控制
  4、隐藏信息,实现细节
  5、良好的封装能够减少耦合

继承:子类可以继承自父类,不仅可以直接使用父类的属性与方法也可以增加自己的方法或重写父类的方法以适应子类的需要。

多态使用父类对象的地方,都可以使用子类对象。或者说使用父类对象可以引用子类变量。

动态绑定:一个对象拥有声明类型,与实际类型。list的声明类型就是List,而实际类型是ArrayList;同时,以list(父类类型的引用)为例,ArrayList(实际类型)中如果实现了toString方法,list就会调用Arraylist(实际类型)的方法,否则才会调用List(父类类型)中的toString方法。

//动态绑定
List<Integer>list = new ArrayList<>();
List<Integer>list = new LinkedList<>();

2.String、StringBuffer和StringBuilder的区别?

String可以理解为字符串常量,而后两者都是字符串变量,当创建了String之后就不可以更改String的长度了,之后的两者可以。StringBuffer是线程安全的,StringBuffer对方法加了同步锁或者对调用的方法加了同步锁。而StringBuilder适用于单个线程。

StringBuilder sb = new StringBuilder();
sb.append(a);
sb.append(b);

3.String a="“和String a=new String(”")的的关系和异同?

通过String a=""直接赋值的方式得到的是一个字符串常量,存在于常量池;注意,相同内容的字符串在常量池中只有一个,即如果池已包含内容相等的字符串会返回池中的字符串,反之会将该字符串放入池中。

而后一种方式会实际的创建一个对象,也就是开启一块内存用来存储对象。
对于String来说,==判断的是两者是否是相同的对象(同一处内存)。而equals是比较内部的值。

 String s1 = new String("");
        String s2 = "";
        System.out.println(s1.length());//0
        System.out.println(s1==s2);//false
        System.out.println(s1.equals(s2));//true

总结:== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重写了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。

4.Object的equal()和==的区别?

==对于基本类型是比较其中的值是否相等,对于引用类型是比较其引用是否相同两个对象的内存地址是否相同)。

equal方法主要取决于Object子类的具体实现,比如Integer和String就是中就是值比较。

5.装箱、拆箱什么含义?

装箱就是把基本类型转换成包装器类型,拆箱就是把包装器类型转换为基本类型。
引申:为什么要使用包装器类型。(泛型的类型擦除)

6.int和Integer的区别

int是基本类型,Integer是int的包装器类型
Integer创建是需要实例化,而int不需要;
Integer实际是对象的引用,创建时,会有一个指针指向引用的对象,而int是直接存储数值。
int的初始值是0,Integer的初始值是null;

7.遇见过哪些运行时异常?异常处理机制知道哪些?

java中异常有两类:Error和Exception。
error是系统中的错误,Exception是可能通过修改代码而避免的异常

Exception又分成两种:IOException(其他异常)和RunTimeException(运行时异常)

运行时异常主要有NoPointerException(空指针异常)和ArrayIndexOutOfBoundException(数组越界异常)。该类异常一般源自程序自身的问题,属于不可查异常

而IOException属于程序外部引起的异常,比如包括FileNotFoundException(文件不存在异常)。属于可查异常,即强制程序员必须进行处理,如果不进行处理则会出现语法错误。
在这里插入图片描述
异常处理机制包括:
(1)接收系统抛出的异常:try,catch,finally,在try中执行可能会抛出异常的操作,在catch中捕捉异常。无论try中执行结束或是捕捉到了异常,都会执行finally中的代码。但是如果try中return,在finally中也return,就会以finally中结果为准。

catch中常用方法(最常用的是3)

e.getMessage():返回异常对象的一个简短描述
e.toString():获取异常对象的详细信息
e.printStackTrace():在控制台上打印异常对象和它的追踪信息

(2)抛出异常:在方法中将异常对象显性地抛出,之后异常会沿着调用层次向上抛出,交由调用它的方法来处理。一旦方法抛出了异常,这个方法就不会返回调用者。

throws:声明抛出的异常,位置在方法名后、异常类型前
throw:抛出异常,一般在方法体内部

切记如果调用一个可以抛出异常的方法就必须处理它或者继续传递。
在这里插入图片描述
(3)自定义异常类:可以自定义异常类继承自Exception或者其他Exception类,然后在接收异常或抛出异常时,把异常更改为我们自定义的异常类即可。

8.什么是反射,有什么作用和应用?

反射可以在程序运行时获取任何一个类的信息(包括成员变量与方法),以及动态的调用类中任意一个对象的所有方法(包括私有的变量以及私有的方法静态常量稍有不同)。调用私有变量以及私有方法需要获取权限,并分别调用私有方法/对象invokeset方法,传入要变更的值,以及要操作的类的实例

//获取变量对应的Class对象
Class mClass = num.getClass();
//获取成员变量
mClass.getFields();
//获取方法
mClass.getMethods();

功能动态性,可以在运行时获取任何一个类的信息,在运行时通过getName获取一个对象所属的类以及在运行时构造任意类的一个对象,也可以在运行时动态的调用任意一个对象的任意方法。

//在运行时构造任意类的一个对象
 TestClass testClass = new TestClass();
testClass.getName().newInstance();

应用是可以和泛型相结合。

9.什么是内部类?有什么作用?静态内部类和非静态内部类的区别?

内部类是定义在一个类中的类。它一共有三个好处:(1)可以使用外部类中的变量;(2)为了节省代码量可以使用内部类(比如创建Handler都需要使用匿名内部类的方式,然后实现内部的handleMessage方法)(3)内部类对同一个包的其他类是隐藏的

内部类中使用外部类的对象:

class OutSide{
private Boolean flag;
...
void start()
{
inside in = new inside();
}
class inside{
if(flag) System.out.println("use Outside params");
}
}

实际是运用了外部类的实例的引用,我们将外部类的实例的引用命名为out。编辑器会默认生成一个构造函数,并在外部类的实例调用start方法后将外部类的实例传入内部类中。

void start()
{
inside in = new inside(this);
}
//构造函数
public inside(OutSide outside){ 
out = outside;
}
//实际是调用了外部类实例的引用
if(out.flag)...

静态内部类:当我们不需要使用外部类的中的变量域时,可以使用静态内部类

静态内部类与非静态内部类的区别
(1)静态内部类是指被声明为static的内部类,可不依赖外部类实例化;而非静态内部类需要通过生成外部类来间接生成

//Pair是Arralg的静态内部类,可以不依赖外部类实例化。
Arralg.Pair p = Arralg.minmax(value)

(2)静态内部类只能访问外部类的静态成员变量和静态方法,而非静态内部类由于持有对外部类的引用,可以访问外部类的所用成员。(可以看到静态内部类无法调用其他变量,只能调用静态成员变量。)图中的normal是红色的可以看出是不可用的
在这里插入图片描述

10.final、finally、finalize()分别表示什么含义

final修饰的变量必须要初始化,且赋初值后不能再重新赋值;final修饰方法代表方法不可被重写,final修饰类代表类不可以被继承。

finally 则是在trycatch中使用的,在trycatch之后会使用finally方法,该方法不论执行完try还是执行完catch中的逻辑都会去执行finally中的代行。但如果finally中和try中同时有return 语句,则会最终返回finally中的,也就是finally的执行顺序在return之前。但有以下四种情况不会执行
(1)finally语句块中发生了异常
(2)在之前的程序中调用了System.exit方法
(3)关闭CPU
(4)程序所在的线程死亡

11.重写和重载的区别?

重写是子类重写父类的方法,或者实现了接口中的方法。
重载是指多个相同名称的方法,不同的形参下对应不同的方法。

12.抽象类和接口的异同?

可以参考我自己的一篇博客深入理解Java的接口和抽象类
抽象类与接口的相同处在于内部都存在抽象方法(接口中没有写方法是抽象的),子类想要继承自抽象类,或者实现接口,都需要实现抽象方法。同时抽象类与接口都不可以有实例

不同之处在于:
(1)抽象类中可以存在一些非抽象方法及各种类型的变量,而接口中方法都是抽象的,同时变量必须是public static final类型;
(2)抽象类与子类的关系是**"是不是"的关系(是抽象类的子类可以继承自抽象类,直接使用一些通用功能,然后实现特殊功能),而类与接口是“有没有”**的关系(类的子类要实现接口,代表有没有这个功能)。
(3)一个类只能继承一个抽象类,而可以实现多个接口
(4)抽象类中可以有静态代码块以及静态方法,接口不可以。

最后:如果是抽象类实现接口,可以不实现全部接口中的方法,留下一些方法给子类实现,但是子类就必须实现未实现的所有方法

不熟悉的知识:
(1)抽象类必须是public或protected
(2)接口中的变量会被隐式地指定为public static final变量,而方法会被隐式地指定为public abstract
(3)对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。因为如果实现接口,需要把接口中所有的抽象方法都重写一次。

13.为什么匿名内部类中使用局部变量要用final修饰?

14.Object有哪些公有方法?

equals方法

用于判断两个对象的引用是否相等。

我们首先来看下Object中是如何处理的

public boolean equals(Object obj) {  
    return (this == obj);  
}  

很显然,String,Integer等类其实就重写了equals方法以比较内容。

举个例子来演示equals的实现机制,我们要求到雇员的姓名,薪水和雇佣日期都相同,两个雇员才是相等的。
(1)直接调用==方法判断是否引用相同(存储在同一块地址),是就直接return true
(2)判断是否传入的对象为null
(3)判断两个对象的类是否相同,只有类相同,才有可能相等。
(4)开始正常比较每一个属性(姓名,薪水,雇佣日期,引用类型用equals比较,而基本类型用==比较
在这里插入图片描述
为了防止两个对象的属性可能为空,使用Objects.equals(a,b)方法,该方法逻辑只要有一个为null,就返回false,两个都为null返回true,否则去调用a.equals(b);
在这里插入图片描述

最后,在子类中在重写equals方法时,则首先要调用父类的equals方法,因为要先满足父类的中的域相等,之后在比较子类的域
在这里插入图片描述

hashCode方法

散列值是由对象导出的一个整型值,一般来说,如果两个对象,散列值一般不同。(引出了为什么HashMap中泛型类型使用自定义类要重写hashCode与equals方法)
在这里插入图片描述
字符串s与t拥有同样的散列码,是因为对于String类型,hashCode是基于内容导出的;而StringBuilder中没有hashCode方法,它的散列码是由Object类的默认hashCode方法导出的对象的存储地址.

小结

1.equals相等的,hashCode(散列值一定相同)
解答:可以想一下,如果二者哈希值不相等,会导致相同的元素存入HashMap不同位置的哈希桶中,这样HashMap的性质就没了
2.hashCode值相等,equals不一定相等
解答:很明显,你想想哈希冲突就知道了,如果散列值相等,就是相同的对象,那不就没有哈希冲突了么,也不需要是哈希桶数组中存放链表形式来存放hashCode相等而不是相同的对象了。

15.java基本类型

1.整形的:int、long、short、byte。1byte等于8bit,一个bit代表一个1或者0,是计算机的基本单位
byte:1字节,8比特,-27 ~ 27-1
short:2字节,16比特,-215~215-1
int:4字节,32比特,-231~231-1
long:8字节,64比特,-263~263-1
在这里插入图片描述
2.浮点型的:float、double
float:4字节,代表单精度浮点型,范围:[-3.4E38,3.4E38]
double:8字节,代表双精度浮点型,范围:[-1.8E308,1.8E308]
在这里插入图片描述
3.字符型的:char
char型变量是用来存储Unicode编码的字符的,可以存储汉字,而Unicode的占2字节,因此char也是占2字节,其范围为[0,65535]。
4.boolean类型的:boolean
boolean在虚拟机中是存储为int型,因此是4个字节,而如果是boolean数组,boolean数组将会被编码成Java虚拟机的byte数组,boolean元素占8位(1个字节)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值