1. java的优势?
- 跨平台
- 安全 健壮
- 免费 开源
- 简单
- 动态的更新
2. JVM (java虚拟机 )包括
- 类加载器 ClassLoader
- 解释执行器 Interfreter
- 字节码校验器 ByteCode Verifier
3. java中的数据类型
- 基本数据类型:4类8种
- 布尔型、字符型、整数型、浮点型
- boolean、char、byte、short、int、long、float、double
- 引用数据类型
4. java中的运算符
- + (加) - (减) * (乘) / (取整) %(取余)
- += -= *= /= %=
- ++ - -
- > (大于) < (小于)>= (大于等于)<= (小于等于)!= (不等于) !(非运算符)= (等于)==(赋值运算符)
- 逻辑运算符:&& || & |
- 按位运算符:& | ^ ~
- 位移运算符:>> << >>>
- 三目运算符:boolean ? 2 : 3
5. 成员变量和局部变量的区别
- 定义的位置不同
a. 成员变量:类体里面 方法体外面
b. 局部变量:方法体里面 - 使用范围不同
a. 成员变量:依赖于对象而存在 只要对象在 那对象中的属性就还在
b. 局部变量:只能作用于他所在的方法体,一旦方法执行完成,局部变量立即消亡 - 默认值问题
a. 成员变量:即使不赋值也有默认值
b. 局部变量:没有默认值,在使用之前必须先赋值 - 局部变量和成员变量重名问题
a. 局部变量和成员变量可以重名
6. 流程控制
- 分支
a. if else
b. switch case (default break) - 循环
a. for
b. while
c. do while
7. 数组
- 定义数组
int[] data = new int[5];
int[][] datas = new int[5][2]; - 获取数组长度
data.length; - 遍历数组
a. for
b. foreach
data[下标] - 数组的复制
System.arraycopy(1,2,3,4,5)
1:要复制的源数组
2:源数组的起始下标位置 (下标)
3:要复制到的目标数组
4:目标数组的起始下标位置
5:要复制的长度
*:其实1 3 部分可以是同一个对象 从而实现数组的前后移动 - 冒泡排序
- 自动排序:
Arrays.sort(数组对象);// 只能从小到大进行排序 - 代码实现
- 自动排序:
for(int x = 0; x < data.length - 1;x++){
for(int y = 0; y < data.length - 1 - x ;y++){
if(data[y] > data[y + 1]){//前大后小
//交换
data[y] = data[y] ^ data[y + 1];
data[y + 1] = data[y] ^ data[y + 1];
data[y] = data[y] ^ data[y + 1];
int temp = data[y];
data[y] = data[y + 1];
data[y + 1] = temp;
}
}
}
8. 面向对象的三大特点:
- 封装、继承、多态
9. StringBuffer和StringBuilder之间的区别?
- 是否允许多个线程同时进行访问
a. StringBuffer
同一时间只允许一个线程同时进行访问,效率较低
但是不会发生并发修改错误
b. StringBuilder
同一时间允许多个线程同时进行访问,效率较高
但是可能会发生并发错误
10. String类常用的方法:
返回类型 | 方法名 | 作用 |
---|---|---|
int | ength() | |
byte[] | getBytes() | |
char[] | toCharArray() | |
String[] | split(String) | |
boolean | equals(String) | |
boolean | equalsIgnoreCase(String) | 忽略大小写的比较两个字符串的内容是否相等 |
boolean | contains(String) | |
boolean | startsWith(String) | |
boolean | endsWith(String) | |
String | toUpperCase() | |
String | toLowerCase() | |
String | replace(String,String) | |
String | replaceAll(String,String) | |
String | replaceFirst(String,String) | |
String | substring(int x1,int y1) | |
String | substring(int) | |
String | trim() | |
和位置有关的方法: | ||
char | charAt(int) | 找到某个位置对应的字符 |
int | indexOf(String) | 找到某个内容第一次出现的位置 |
int | lastIndexOf(String) | 找到某个内容最后一次出现的位置 |
11. Vector和ArrayList之间的区别?
- 同步特性不同
ArrayList同一时间允许多个线程同时进行访问 效率高
但是可能发生并发修改错误
Vector同一时间只允许一个线程同时进行访问 效率低
但是他不会出现并发修改错误
从5.0开始 Collections.synchroniezedList()
可以将一个线程不安全的ArrayList变成一个支持
线程安全的List集合 所以Vector渐渐退居二线 - 底层扩容机制不同
a. ArrayList
6.0及之前 7.0及之后
x*3/2+1 x+(x >> 1)
b. Vector
new Vector(10); new Vector(10,3);
* 2 + 3 - 出现的版本不同
Vector since jdk 1.0
ArrayList since jdk 1.2
12. LinkedList和ArrayList之间的区别?
他们底层采用的实现方式就不同 从而他们的优劣势也就不同
ArrayList底层用数组实现的
数组的优势:查找遍历 随机访问 但是劣势体现在添加删除元素
LikedList底层用链表实现的:
链表的优势:添加删除元素比较简单 但是劣势体现在遍历查找
13. HashMap和HashTable的区别
-
同步特性不同
HashMap 同一时间允许多个线程同时进行操作
效率较高但是可能出现并发错误!
Hashtable 同一时间只允许一个线程进行操作
效率较低但是不会出现并发错误! -
对于null的处理不同
HashMap 无论主键还是值 都可以存放null
只不过由于主键要求唯一 所以主键只能有一个null
Hashtable 无论主键还是值 都不能存放null
它对于null “零容忍” 出现null直接报异常 -
底层实现的细节不同
HashMap 底层默认分16小组 分组组数可以随意指定
但是最终结论一定是2的n次方数
计算散列分组:hash & (分组组数-1)
Hashtable 底层默认分11小组 可以随意指定 真的随意分
计算散列小组:hash % 分组组数 -
出现的版本不同
HashMap since JDK1.2
Hashtable since JDK1.0 (Vector)
14. Comparable和Comparator的区别
-
包结构就不同
java.lang.Comparable 语言基础包
java.util.Comparator 常用工具包 -
代表的含义截然不同
Comparable 一个类型是有能力比较的
Comparator 一个类型是另一个类型比较的工具 -
当中的抽象方法也不同
Comparable -> compareTo(1)
Comparator -> compare(1,2)
class Student implements Comparable<Student>{
...
}
这是在描述学生类是可以比较的类型 学生自身有排序规则
class Student implements Comparator<Teacher>{
...
}
这是在描述学生类是比较老师专用的标尺
15. 为什么要使用内部类
- 内部类是共享数据最最简单的方式之一
16. 内部类的分类
- 成员内部类:new Outer().new Inner();
- 静态内部类:new Outer.Inner();
- 局部内部类:外部类所有(静态)成员+ new Inner();位置限定
final修饰的局部变量 类定义之后 所在方法结束之前 - 匿名内部类:
优势有二:
1.省略掉一个毫无意义的类名
2.能够让开发的流程更加连贯
//new的是一个继承了父类或者实现了接口的没有名字的类的对象
new 父类/接口<>(){
@Override
//完成方法覆盖 或者 方法实现
};
17. final和finalize()和finally的区别
18. throw和throws的区别
19. 多线程 【面试题】
- 控制线程的方式
a. setPriority(int); 设置线程优先级别 可选范围1-10 默认为5
*:不推荐使用
b. static sleep(long); 让当前线程休眠指定的毫秒数
c. static yield(); 让当前线程放弃已经拿到的时间片 直接返回就绪状态
d. join(); 一个线程邀请另一个线程优先执行 - 一些方法
a. setName() + getName() : 设置和得到线程的名字
b. static activeCount() : 得到程序当中所有活跃[就绪+运行+阻塞]线程的总数
c. static currentThread() : 得到正在运行状态的那个线程对象
d. setDaemon(true) : 设置线程成为守护线程
*:守护线程是给其他线程提供服务的 当程序当中只有守护线程的时候
守护线程自行结束[哪怕当中是while(true)也会自行结束]
Java当中的gc 就是一个系统级别的守护线程
e. interrupt() : 中断 打断 线程的阻塞状态
20. 如何解决并发错误
- 利用修饰符synchronized 同步的
- java.util.concurrent.locks.ReentrantLock
lock();
unlock();
21. 死锁如何解决
- 线程间相互通讯:
wait(): 让当前线程 放弃所有[锁标记+时间片]已经持有的资源
直接进入调用方法的那个对象的等待池[等待队列]
notify(): 从调用方法的那个对象的等待池当中随机的唤醒一个线程
notifyAll():从调用方法的那个对象的等待池当中唤醒所有线程
*:这三个方法都必须在已经持有对象的锁标记的前提下才能调用
如果我们要调用x.wait() 或者 x.notify()
必须保证已经拿到了x的锁标记才行
所以 x.wait() 和 x.notify()
一定都会出现在synchronized(x){
当中!
}
22. 锁池和等待池的区别
-
进入的时候是否需要释放资源
锁池:不需要释放资源 (所以才会形成死锁啊)
等待池:需要释放所有[锁标记+时间片]资源 -
离开的时候是否需要调用代码
锁池:不需要调用 一旦锁标记归还 线程自动归位
等待池:需要调用notify() 或者 notifyAll() -
离开之后去哪里了
锁池:离开之后直奔就绪
等待池:离开之后直奔锁池!