面试题
- 1、面向对象的特征是什么?
- 2、String是基本数据类型吗?
- 3、“==” 和equal() 的区别?
- 4、short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?
- 5、int和integer的区别?
- 6、&和&&的区别?
- 7、数组有没有length()方法?String有没有length()方法?
- 8、是否可以继承String类?
- 9、简单讲述一下final的关键字?
- 10、String,StringBuffer和StringBuilder区别?
- 11、重载(Overload)和重写(Override)的区别?
- 12、类加载器主要有哪几种?
- 13、抽象类(abstract class)和接口(interface)的异同?
- 14、String s = new String(“xyz”);创建了几个字符串对象?
- 15、指出下面程序的运行结果。
- 16、你常见的运行时异常?
- 17、Servlet的生命周期?
- 18、Java创建对象有哪几种方式?
- 19、Java集合的问题
- 20、类加载器的生命周期?
- 21、多线程有哪几种实现方式?
- 22、Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?
- 23、JDK 和 JRE 有什么区别?
- 24、 String 类的常用方法都有那些?
- 25、线程的 run() 和 start() 有什么区别?
- 26、什么是死锁?
1、面向对象的特征是什么?
抽象、继承、封装、多态
2、String是基本数据类型吗?
不是,String是对象。java中的基本数据类型只有8个分别是byte、short、int、float、long、double、char、boolean;
3、“==” 和equal() 的区别?
"== "对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重写了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。(两者在本质上是一样的)
4、short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?
对于short s1 = 1; s1 = s1 + 1;由于1是int类型,因此s1+1运算结果也是int 型,需要强制转换类型才能赋值给short型。而short s1 = 1; s1 += 1;可以正确编译,因为s1+= 1;相当于s1 = (short)(s1 + 1);其中有隐含的强制类型转换。总结:s1+=1可以自动强制转换成int类型,而s1=s1+1却不能自动强制转换数据类型。
5、int和integer的区别?
Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrapper class),int的包装类就是Integer,从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。
class AutoUnboxingTest {
public static void main(String[] args) {
Integer a = new Integer(8); // 将3自动装箱成Integer类型
Integer b = 8;
int c = 8;
System.out.println(a == b); // false 两个引用没有引用同一对象
System.out.println(a == c); // true a自动拆箱成int类型再和c比较
}
}
最近还遇到一个面试题,也是和自动装箱和拆箱有点关系的,代码如下所示:
public class Test03 {
public static void main(String[] args) {
Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
System.out.println(f1 == f2);
System.out.println(f3 == f4);
}
}
如果不明就里很容易认为两个输出要么都是true要么都是false。首先需要注意的是f1、f2、f3、f4四个变量都是Integer对象引用,所以下面的==运算比较的不是值而是引用。装箱的本质是什么呢?当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
简单的说,如果整型字面量的值在-128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象,所以上面的面试题中f1==f2的结果是true,而f3==f4的结果是false。
6、&和&&的区别?
&是位操作符,不具备短路特效;而&&是逻辑操作符,逻辑运算符具有短路的特效。&&短路运算:如果&&左边的表达式的值是false,右边的表达式会被直接短路掉,不会进行运算。
例如在验证用户登录时判定用户名不是null而且不是空字符串,应当写为:username != null &&!username.equals(“”),二者的顺序不能交换,更不能用&运算符,因为第一个条件如果不成立,根本不能进行字符串的equals比较,否则会产生NullPointerException异常。
public class Test{
static String name;
public static void main(String[] args){
if(username!=null & username.equals("")){
System.out.println("ok");
}else{
System.out.println("erro");
}
}
}
以上代码将会抛出空指针异常
7、数组有没有length()方法?String有没有length()方法?
数组没有length()方法,有length 的属性。String 有length()方法。
8、是否可以继承String类?
不可以,String 类是final类,不可以被继承。
9、简单讲述一下final的关键字?
类、变量、方法
final修饰的类叫最终类,该类不能被继承。
final修饰的方法不能被重写。
final修饰的变量叫常量,常量必须初始化,初始化之后值不能被修改。
10、String,StringBuffer和StringBuilder区别?
String是字符串常量,final修饰,意味着String引用的字符串内容是不能被改变的。
StringBuffer是字符串变量,表示的字符串对象可以直接进行修改(线程安全)。
StringBuilder是字符串变量,表示的字符串对象可以直接进行修改,但线程不安全,在单线程环境下使用,因为它的所有方面都没有被synchronized修饰,因此它的效率也比StringBuffer要高。
11、重载(Overload)和重写(Override)的区别?
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;
重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。
12、类加载器主要有哪几种?
1、启动类加载器(Bootstrap ClassLoader)用来加载java核心类库,无法被java程序直接引用。
2、扩展类加载器(extension classLoader)他用来加载java的扩展类库。java虚拟机的实现会提供一个扩展目录,该类加载器在此目录中查找并加载java类。
3、系统类加载器(System classLoader)根据java的应用类是由它来完成加载的。可以通过ClassLoader.getSystemClassLoad()来获取它。
4、用户自定义类加载器,通过继承java.lang.ClassLoader类获取的实现方式。
13、抽象类(abstract class)和接口(interface)的异同?
同:
- 抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用
- 一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法(接口中的方法)全部进行实现。
异:
- 抽象类只能被继承,而且只能单继承。接口需要被实现,而且可以多实现。
- 抽象类中可以定义非抽象方法,子类可以直接继承使用。接口中都有抽象方法,需要子类去实现。
- 抽象类使用的是 is a 关系。接口使用的 like a 关系。
- 抽象类的成员修饰符可以自定义(private、默认、public、protected)。接口中的成员修饰符是固定的。
成员变量: public static final ;
成员方法: public abstract 。
14、String s = new String(“xyz”);创建了几个字符串对象?
两个对象,如果常量池中的没有“xyz”,一个是在常量池中创建”xyz”,一个是用new创建在堆上的对象。
15、指出下面程序的运行结果。
class A {
static {
System.out.print("1");
}
public A() {
System.out.print("2");
}
}
class B extends A{
static {
System.out.print("a");
}
public B() {
System.out.print("b");
}
}
public class Hello {
public static void main(String[] args) {
A ab = new B();
ab = new B();
}
}
执行结果:1a2b2b。
创建对象时构造器的调用顺序是:先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。
16、你常见的运行时异常?
- NullPointerException 当应用程序试图访问空对象时,则抛出该异常。
- SQLException 提供关于数据库访问错误或其他错误信息的异常。
- IndexOutOfBoundsException指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。
- NumberFormatException当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
- FileNotFoundException当试图打开指定路径名表示的文件失败时,抛出此异常。
- IOException当发生某种I/O异常时,抛出此异常。此类是失败或中断的I/O操作生成的异常的通用类。
- ClassCastException当试图将对象强制转换为不是实例的子类时,抛出该异常。
- ArrayStoreException试图将错误类型的对象存储到一个对象数组时抛出的异常。
- IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数。
- ArithmeticException当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例。
- NegativeArraySizeException如果应用程序试图创建大小为负的数组,则抛出该异常。
- NoSuchMethodException无法找到某一特定方法时,抛出该异常。
- SecurityException由安全管理器抛出的异常,指示存在安全侵犯。
- UnsupportedOperationException当不支持请求的操作时,抛出该异常。
- RuntimeExceptionRuntimeException 是那些可能在Java虚拟机正常运行期间抛出的异常的超类。
17、Servlet的生命周期?
生命周期有5部分:加载,初始化,服务,销毁,卸载
18、Java创建对象有哪几种方式?
1、采用new
2、通过反射
3、采用克隆
4、通过序列化机制
前2者都需要显式地调用构造方法,造成耦合性最高的恰好是第一种,因此你发现无论什么框架,只要涉及到解耦必先减少new的使用。
19、Java集合的问题
java集合整理https://blog.csdn.net/qq_43228581/article/details/106176252
1、HashMap 和 Hashtable 有什么区别?
- 存储:HashMap 运行 key 和 value 为 null,而 Hashtable 不允许。
- 线程安全:Hashtable 是线程安全的,而 HashMap 是非线程安全的。
- 推荐使用:在 Hashtable 的类注释可以看到,Hashtable 是保留类不建议使用,推荐在单线程环境下使用 HashMap 替代,如果需要多线程使用则用 ConcurrentHashMap 替代
2、List、Set、Map 之间的区别是什么?
List、Set、Map 的区别主要体现在两个方面:元素是否有序、是否允许元素重复。
3、ArrayList 和 LinkedList 的区别是什么?
- 数据结构实现:ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。
- 随机访问效率:ArrayList 比 LinkedList 在随机访问的时候效率要高,因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。
- 增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList
- 增删操作要影响数组内的其他数据的下标。
综合来说,在需要频繁读取集合中的元素时,更推荐使用 ArrayList,而在插入和删除操作较多时,更推荐使用 LinkedList。
4、如何实现数组和 List 之间的转换?
- 数组转 List:使用 Arrays. asList(array) 进行转换。
- List 转数组:使用 List 自带的 toArray() 方法。
5、如何决定使用 HashMap 还是 TreeMap?
对于在 Map 中插入、删除、定位一个元素这类操作,HashMap 是最好的选择,因为相对而言 HashMap 的插入会更快,但如果你要对一个 key 集合进行有序的遍历,那 TreeMap 是更好的选择。
6、ArrayList 和 Vector 的区别是什么?
- 线程安全:Vector 使用了 Synchronized 来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。
- 性能:ArrayList 在性能方面要优于 Vector。
- 扩容:ArrayList 和 Vector 都会根据实际的需要动态的调整容量,只不过在 Vector 扩容每次会增加 1 倍,而 ArrayList 只会增加 50%。
7、Array 和 ArrayList 有何区别?
- Array 可以存储基本数据类型和对象,ArrayList 只能存储对象。
- Array 是指定固定大小的,而 ArrayList 大小是自动扩展的。
- Array 内置方法没有 ArrayList 多,比如 addAll、removeAll、iteration 等方法只有 ArrayList 有。
8、 在 Queue 中 poll()和 remove()有什么区别?
- 相同点:都是返回第一个元素,并在队列中删除返回的对象。
- 不同点:如果没有元素 poll()会返回 null,而 remove()会直接抛出 NoSuchElementException 异常。
20、类加载器的生命周期?
- 加载
- 链接(包括三部分)
- 验证
- 准备
- 解析
- 初始化
- 使用
- 卸载
21、多线程有哪几种实现方式?
1、继承Thread类
2、实现Runnable接口(推荐使用)
两种方式都要通过重写run()方法来定义线程的行为,推荐使用后者,因为Java中的继承是单继承,一个类有一个父类,如果继承了Thread类就无法再继承其他类了,显然使用Runnable接口更为灵活。
22、Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?
- sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复。
- wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。
23、JDK 和 JRE 有什么区别?
- JDK:Java Development Kit 的简称,Java 开发工具包,提供了 Java 的开发环境和运行环境
- JRE:Java Runtime Environment 的简称,Java 运行环境,为 Java 的运行提供了所需环境。
具体来说 JDK 其实包含了 JRE,同时还包含了编译 Java 源码的编译器 Javac,还包含了很多 Java 程序调试和分析的工具。简单来说:如果你需要运行 Java 程序,只需安装 JRE 就可以了,如果你需要编写 Java 程序,需要安装 JDK。
24、 String 类的常用方法都有那些?
- indexOf():返回指定字符的索引。
- charAt():返回指定索引处的字符。
- replace():字符串替换。
- trim():去除字符串两端空白。
- split():分割字符串,返回一个分割后的字符串的组成。
- getBytes():返回字符串的byte类型分组。
- length():返回字符串长度。
- toLowerCase():将字符串转成小写字母。
- toUpperCase():将字符串转成大写字符。
- substring():截取字符串。
- equals():字符串比较。
25、线程的 run() 和 start() 有什么区别?
start() 方法用于启动线程,run() 方法用于执行线程的运行时代码。run() 可以重复调用,而 start() 只能调用一次。
26、什么是死锁?
当线程 A 持有独占锁a,并尝试去获取独占锁 b 的同时,线程 B 持有独占锁 b,并尝试获取独占锁 a 的情况下,就会发生 AB 两个线程由于互相持有对方需要的锁,而发生的阻塞现象,我们称为死锁。
【什么是死锁代码详解】https://blog.csdn.net/qq_43228581/article/details/106447442