1.接口、抽象类的异同点
-
从继承的角度:接口是多继承,多实现
抽象类是单继承
-
从成员角度:接口的变量都是 公共的 static final
抽象类中既可以由public static final 修饰的,也可以由普通属性
接口中的方法:必须是抽象方法或default修饰的方法
抽象类中的方法,既可以有普通方法,也可以有抽象方法
-
从构造角度:接口无没有构造方法,抽象类有构造方法。
-
都不能被new
2.方法重载和重写的区别
重载:
发生在同一个类中
方法名相同,参数不同(个数,顺序,类型)与访问修饰符、返回值类型无关
好处:同一类型的操作,记住同意方法名即可,方便调用。
重写:
发生在子类中
方法名相同,参数相同,访问修饰符不能小于父类的访问修饰符,返回值相同或者是其父类
好处:实现了多态
public void test(Animal animal){
}
3.多态的实现方式?有什么区别?
有两种:方法的重载和重写
从编译、调度角度的区别?
方法重载:静态实现多态,重载的方法被编译时就已经确定、被编译成字节码文件,供调用。
方法重写:动态实现多态,在编译时 ,子类的方法并没有覆盖调父类的方法体,而是在调用的时候,new出的是哪个子类的对象,就是用哪个子类的对象的方法体去覆盖调父类中的方法。
4.String的常见方法
String是不可变字符串,因为它的底层是使用final修饰的字符串数组进行存储的,每当进行字符传拼接得到不同的字符串时,都会在常量池中new一个新对象。所以在频繁改变字符串的值的时候不建议使用。
/** The value is used for character storage. */
private final char value[];
1.length()
2.subString()
3.split()
4.equals()
5.indexOf()
6.lastIndexOf()
7.charAt()
8.replace()
9.compareTo()
10.matches()
11.replaceAll()
12.endsWith()
13.startsWith()
14.trim()
15.equalsIgnoreCase()//字符串比较,忽略大小写
16.concat()
使用 | 方法名 | 含义 | 返回值 |
---|---|---|---|
字符串长度 | 字符串.length() | 字符串长度,汉字按照一个 | 返回字符串个数 |
查找单个字符 | 字符串.charAt(下标) | 字符串有下标,从0,对应下标的一个字符 | 一个字符 |
字符串截取 | 字符串.substring(开始下标) | 从下标截取到最后 | 截取的新的字符串子串 |
字符串截取 | 字符串.substring(开始,结束) | 从开始到结束截取字符串 | 字符串 |
切割 | 字符串.split(切割原则) | 字符串分割,注意转义字符 | 字符串数组 |
查找字符串 | 字符串.indexOf(子串) | 从字符串中查找是否存在子串(左向右) | 第一次的下标(找不到返回-1) |
查找字符串 | 字符串.lastIndexOf(子串) | 从字符串中查找是否存在子串(右向左) | 最后一次出出现的下标(找不到返回-1) |
比较内容 | 字符串.equals(参数串) | 参数串和内容是否相同 | boolean |
比较顺序 | 字符串.compareTo(参数串) | 比较字典顺序 | 0(相同)负的 正的 |
替换 | 字符串.replace(old,new) | 将old替换成new | 替换后的新串 |
正则校验 | 字符串.matches(正则) | 匹配正则表达式 | boolean值 |
字符串.endsWith() | 字符串尾部匹配 | boolean值 | |
字符串.startsWith() | 字符串首部匹配 | boolean值 | |
字符串.trim | 去除两端空白 | 新鲜的字符串 |
5.StringBuffer和StringBulider的区别?
StringBulider效率高,允许多线程操作,线程不安全。
StringBuffer是线程安全的,效率低。
6.排序算法:冒泡,选择,
int[] ary = {2, 4, 6, 1, 9};
// 冒泡排序,将数组元素两两比较,目的是,小的上浮,大的下沉,直到最后一次,最大的在最下面,后续按照其道理继续执行,直到有序。
for (int i = 1; i < ary.length; i++) {
for (int j = 0; j < ary.length - i; j++) {
if (ary[j] < ary[j + 1]) {
int t = ary[j];
ary[j] = ary[j + 1];
ary[j + 1] = t;
}
}
}
System.out.println(Arrays.toString(ary));
// 选择排序,从头开始,将数组的每一个元素依次与它后面的元素进行比较,交换。
for (int i = 0; i < ary.length; i++) {
for (int j = i + 1; j < ary.length; j++) {
if (ary[i] > ary[j]) {
int t = ary[i];
ary[i] = ary[j];
ary[j] = t;
}
}
}
System.out.println(Arrays.toString(ary));
7.线程安全的单例模式
public class Singleton{
//唯一实例
private static Singleton s = null;
//构造方私有化
private Singleton(){
}
//使用方法返回一个实例对象
public static Sibgleton get(){
synchronized(Singleton.class)
if(s==null){
s = new Singleton();
}
}
return s;
}
8.异常
有两种方式处理异常:
捕获 try-catch
抛出异常 throw throws
程序员自己构建一个异常类型,需要继承异常父类:RuntimeException或者Exception。
public class AgeException extends Exception{
/**
* 序列号
*/
private static final long serialVersionUID = 1L;
public AgeException() {
super();
// TODO Auto-generated constructor stub
}
public AgeException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
}
/**
* 检测年龄是否合法
* @throws AgeException
*/
public static void checkAge(int age) throws AgeException {
if(age > 0 && age < 150) {
System.out.println("年龄合法");
}else {
throw new AgeException("年龄非法");
}
}
异常类型:运行时异常RunTimeException
受检时异常 CheckedException,必须对可能出现的异常进行处理,否则编译不通过
9.final、finally、finalize区别
final修饰变量就是常量
修饰方法,不能被子类重写
修饰类,不能再有子类
finally 捕获异常时使用,无论代码是否发生异常,finally里的语句都会执行
作用:释放资源的代码
finalize:是Object的方法,用于通知JVM的垃圾回收器,可以回收当前对象,但不是立即回收
10.Object类的常用方法,及作用
1.public native int hashCode();//返回一个hash值
2.public boolean equals(Object obj) {
return (this == obj);
}//字符串比较
3.protected native Object clone() throws CloneNotSupportedException;//克隆
4.public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}//转换成字符串的toString方法
5.public final native void notify();//唤醒某一个等待的线程的方法
6.public final native void notifyAll();//唤醒全部等待的线程
7. public final native void wait(long timeout) throws InterruptedException;//线程等待
public final void wait(long timeout, int nanos) throws InterruptedException
public final void wait() throws InterruptedException {
wait(0);
}
8.protected void finalize() throws Throwable { }/通知GC,回收该对象
11.进程和线程的区别?
一个运行的应用程序就是一个进程,进程中的一个执行任务称为一个线程。一个线程中包含多个进程。
一个进程是程序运行的基本单位,需要开辟内存空间。
线程是进程的最小执行单位,不需要开辟内存空间。
12.线程的实现方式?
-
继承线程类 extends Thread
-
实现Runable接口
-
实现Callable接口
-
从线程池中获取线程,实现多线程开发
13.Runable、Callable的区别
Callable 在主线程中能够获取子线程方法的返回值,还能获取子线程的异常信息
14.线程的状态有哪些?状态之间如何转换?
新建状态:new
start();
就绪状态:线程对象.start(); 可以配CPU的时间片轮转到
run();
运行状态:CPU的时间片轮转到(可以通过yield()回到就绪状态)
sleep(); join(); wait(); 遇到锁
阻塞状态:
阻塞状态的线程只能转换到就绪状态,不能直接到运行状态;
sleep() 休眠结束后,自动进入就绪状态
wait() 等待调用notify,notifyAll 唤醒,唤醒后就进入继续状态
遇到锁 待锁释放后,重新竞争锁,谁竞争到,谁就进入就绪状态
死亡状态:线程执行结束
15.sleep()和wait()的区别
都是从线程的运行状态,转为阻塞状态
-
sleep()属于Thread类的,wait方法属于Object类
-
sleep()休眠后自动进入就绪状态
wait()需要notify()唤醒,才能进入就绪状态
-
sleep()在线程休眠的过程中,锁不释放,俗称:抱着锁睡
wait()在等待的过程中,首先要释放锁
-
sleep()可以在任意位置调用
wait()只能用在锁里,否则报异常
16.内存泄漏,内存溢出
内存溢出:没有可用的内存。
内存泄漏:存在无法回收的内存,内存泄漏的结果就是内存溢出
class A{
B b =new B();
}
class B{
A a=new A();
}
给每个对象添加一个计数器,如果对象被使用就+1 GC之回收计数为0的对象
17.&& 和 &的区别
&&:短路与,一侧为假,另一侧直接不看
&:两侧都看
18.现成的锁有哪些?什么区别
sychronized 同步锁,同步代码块,同步方法
任意非空对象都可以作为同步代码块的锁的对象
lock 需自行加锁,解锁
区别:
-
sychornized是在字节码层面,在编译的时候,通过字节码添加的锁,通过监视变量monitor来加锁,当一个线程执行锁里面的代码时,首先判断monitor变量的值,如果值为1,则当前线程阻塞,如果值时0,那么就进入锁中(MonitorEnter),同时改变monitor的值为1,当执行完锁中的代码后(MonitorExit),首先把monitor改为0;
-
sychronized是非公平锁,当锁释放后,再次获取锁的线程,并没有顺序,可能最后请求的线程,先获得锁。
-
重量级:没有锁的线程会阻塞
-
-
Lock锁,相当于Java中的逻辑判断代码
-
可以设置为公平锁,也可以设置为非公平锁。
-
可以是重量级,也可以是轻量级锁;遇到所后不阻塞,不短的尝试获取锁,造成CPU的浪费。
-