1. int和Integer的区别?
int是基础数据类型,Integer是类型,是int的包装类。
装箱:把int包装成Integer(类似的还有Long和long,Float和float)
Integet a = 100;
拆箱:把Integer类型的对象简化成int类型
int a = new Integer(100);
2. StringBuilder和StringBuffer的区别?
StringBuffer是线程安全的,StringBuilder是Java SE5新引入的,速度更快,非线程安全。
3. Java的基本数据类型有哪些?
有8个,byte(1),short(2),int(4),long(8),float(4),double(8),char(2),boolean(1)
括号内是字节数。
4. 成员变量修饰符final和static的含义?
final修饰的变量声明后就不能被修改。
static修改的是静态变量,类的所有对象共享一个变量。
5. Error和Exception的区别?
Error是系统级别的错误,很难恢复,程序不必处理,如内存溢出。
Exception是程序应该捕获或处理的异常,是实现的问题。
6. 线程和进程的区别?
进程是运行的程序,有独立的内存空间。
线程是进程内部的一个执行序列,一个进程可以有多个线程,多个线程共享内存空间。
7. 创建一个线程的两种方式?哪种比较好?
继承Thread类和实现Runnable接口。
实现Runnable接口的方式比较好,因为继承意味着耦合,而且Java是单继承的机制,继承了Thread类意味着不能继承其他父类。
还有使用Excutor线程池的方式。
8. Java类的hashcode方法和equals方法?
所有Java都是继承自Object,如果没有重写equals方法,比较的是地址。
String等类型已经重写了equals方法,比较的是String的值。
这两个方法一般同时重写或都不重写。
equals相等的两个对象有相同的hashcode。
但两个对象有hashcode的时候equals不一定相等,可能是hashcode方法的实现有问题导致。
9. 两个对象或变量的==和equal方法的区别?
(1)基本数据类型:基本数据类型变量==比较的是值,没有equals方法
(2)非基本数据类型:==比较的是地址,equals方法要看是否重写了
(3)重写了equals方法:看方法的实现。String,Integer等包装类型Java已经重写了,比较的是值
(4)没有重写equals方法:比较的是地址
10. PreparedStatement和Statement的对比
PreparedStatement有数据库预编译,能重用,提高查询效率
PreparedStatement能预防SQL注入攻击,数据库不会将参数视为SQL指令的一部分来处理,而是在编译完成后才套用参数
PreparedStatement能动态参数化查询,更灵活。
11. 堆内存和栈内存的区别
栈(stack):也叫堆栈,存取速度较快,仅次于CPU寄存器,存放基本数据类型变量和对象的引用
堆(heap):存放对象,由垃圾回收机制管理
12. static关键字的作用?类可以用static修饰吗?
static变量:静态变量,类的所有实例共享,只分配一块内存空间。
static方法:无需实例化即可调用的方法,static方法只能调用其他static方法(非static方法可以调用static方法),访问static变量。
static类:只有内部类可以声明为static,可以直接作为一个类来使用。
static代码块:JVM加载类的时候执行,只会执行一次。
内部类可以用static修饰。
13. final关键字的作用?
final常量:和变量相对,是不可变的。final基本类型常量表示其值不变,final对象表示其引用不变,只能指向初始化时的那个对象,但对象本身是可变的。
final参数:基本类型参数表示不可在方法中改变其值,对象参数表示不可在方法中改变其引用。主要用来向匿名内部类传递数据。
final方法:继承的类不可重写。过去还出于对效率的考虑。
类中private方法都隐式的指定为final。
final类:不能被继承。final类中的所有方法都隐式的指定为final。
14. 重载和重写的区别?
重写(override)也叫覆盖、覆写。
重写用于子类对父类某个方法的重新实现或类对接口的实现,可以用注解@Override来表示,如果加了注解又没有重写,编译器会报错;反之可以,即重写的方法不强制加@Override注解。
重载(overload)一般是指一个类中有两个或以上的方法,方法名相同而参数列表不同。
15. 向上转型和向下转型?
向上转型是指子类的对象转换成父类的对象,向下则相反。
向上转型是安全的,但可能会丢失子类特有的方法和属性,丢失的方法可以通过向下转型重新获得,向下转型需要强制转换,且可能抛出ClassCastException。
“是否有向上转型的需要”也可以用来判断类设计时是否要采用继承,比如需要在一个集合中操作一些不同类型的对象,就可以用继承:定义该集合存放基类,可以直接将子类对象放进去,这时向上转型,然后可以将对象取出来,向下转型成子类,重新获得子类特有的方法和属性。
16.compareTo方法和compare方法的区别?
compareTo是Comparable接口的一个方法,主要用于方法的比较、排序(容器中)等。
compare是Comparator接口的一个方法,用于定义两个对象的比较结果。
compareTo方法的使用:
public class User implements Comparable<Object> { // 实现了Comparable接口
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 重写compareTo方法,定义两个对象的比较
*/
public int compareTo(Object arg0) {
if (this == arg0) {
return 0;
} else {
if (arg0 != null && arg0 instanceof User) {
User user = (User) arg0;
if (this.id > user.getId()) {
return 1;
} else if (this.id == user.getId()) {
return 0;
} else {
return -1;
}
} else {
return -1;
}
}
}
}
public class Test {
/**
* 定义比较器comparator
*/
private static Comparator<User> userComparator = new Comparator<User>() {
public int compare(User arg0, User arg1) {
if (arg0.getId() > arg1.getId()) {
return 1;
} else if (arg0.getId() == arg1.getId()) {
return 0;
} else {
return -1;
}
}
};
public static void main(String[] args) {
User user1 = new User();
User user2 = new User();
User user3 = new User();
user1.setName("user1");
user2.setId(2);
user2.setName("user2");
user3.setId(3);
user3.setName("user3");
List<User> users = new ArrayList<User>();
users.add(user1);
users.add(user3);
users.add(user2);
users.sort(userComparator); // 使用自定义的比较器进行排序
for (User user : users) {
System.out.println(user.getName());
}
}
}
17.Class.forName()方法的作用?
(1)Class.forName()用于加载类,可以在程序运行时动态生成类的对象,比如:
ClassA a = (ClassA)Class.forName(className).newInstance();
传入className,即类的名称,生成该类的对象,为多态提供了很好的支持,即ClassA设计成一个基类或接口,而className是继承了基类或实现了接口的多个不同的子类的名称。
(2)Class.forName()还可以用于加载数据库驱动。
(3)类被加载的时候静态代码段会被执行。
18.什么是可变参数?
可变参数是指一个方法的形参允许传入个数不确定的类型参数,如下函数test,可传入一个或多个int。
public class Test {
public static void main(String[] args) {
test(1);
test(1, 2);
}
public static void test(int ... numbers) {
for (int a : numbers) {
System.out.println(a);
}
}
}
19. 数组和List容器的区别,之间的相互转换
(1)数组长度固定,容器可变
(2)数组只能存储指定类型的对象,容器可以存储任意类型对象
(3)数组效率较高,访问很快,容器开销较大,效率较低
数组和List的相互转换:
// 数组转换为List
public static void arrayToList() {
String[] stringArray = new String[]{"a", "b"};
List<String> stringList = Arrays.asList(stringArray);
for (String str : stringList) {
System.out.println(str);
}
}
// List转换为数组
public static void listToArray() {
@SuppressWarnings("serial")
List<String> stringList = new ArrayList<String>(){{
add("a");
add("b");
}};
String[] stringArray = (String[]) stringList.toArray(new String[0]); // List有两个toArray方法
for (String str : stringArray) {
System.out.println(str);
}
}
List的toArray()方法有带参数和不带参数两个重载。
如果调用不带参数的方法,会抛出ClassCastException:[Ljava.lang.Object; cannot be cast to [Ljava.lang.String;,数组也是一种类型,[Ljava.lang.Object类型不能转化为[Ljava.lang.String类型。
带参数的toArray()方法会构造一个长度和list一样的空数组。
20. 深复制和浅复制的区别?
也叫深克隆和浅克隆。
浅复制只复制当前的对象,不复制对象所引用的其他对象。
深复制要把复制的对象所引用的其他所有对象也复制一份。
21. 什么是Native方法?
native方法是原生的函数,即用C/C++实现的,被编译成DLL,由Java去调用。
22. String类为什么是final的?
出于“安全性”和“效率”。
final修饰的类不能被继承,所以不会被修改,保证了安全性。
String使用非常频繁,定义成final可以提高效率。
23. ArrayList和LinkedList的区别?
ArrayList的实现基于动态数组,LinkedList的实现基于链表。
ArrayList随机访问较快。
LinkedList插入较快。