1、简单讲一下Java的跨平台原理
由于各操作系统支持的指令集不是完全一致的,就会让我们程序在不同的操作系统上要执行不同的程序代码。Java开发了适用于不同操作系统及位数的Java虚拟机来屏蔽各个系统之间的差异,提供统一的接口。只需要在不同的系统上安装对应不同Java虚拟机、Java程序只要遵循Java规范,就可以在操作系统上面运行Java程序。
Java通过不同的系统、不同版本、不同位数的Java虚拟机来屏蔽不同的系统指令集差异而对外提供统一的接口,只需要开发接口即可
2、Java中int类型数据站几个字节?
int 4字节 32位
boolean 1位
3、面向对象的特征有哪些方面?
有四大基本特征:封装、抽象、继承、多态
1、封装:
即将对象封装成一个高度自治和相对封闭的类,对象属性由这个对象自己的方法来读取和改变。
2、抽象:
找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处,并忽略与当前主题和目标无关的那些方面,将注意力集中在与当前目标有关的方面
3、继承:
在定义和实现一个类的时候,可以在一个已经存在的类的基础上来进行,把这个类所定义的内容作为自己的内容,并加入新的内容,或修改原来的方法使之更加适合特殊的需求
4、多态
程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定(引用变量发出的方法调用到底是哪个类中实现的方法,必须由程序运行期间才能确定)
4、有了基本的数据类型,为什么还需要包装数据类型?
Java是一个面向对象的语言,而基本的数据类型不具备面向对象的特性
5、装箱和拆箱
1、装箱:把基本数据类型转化为包装类型
2、拆箱:反之
6、‘==’和equals有什么区别?
1、== 是一个操作符,用于判断两个变量之间的值是否相等,变量可以分为基本类型变量、引用类型变量。如果是基本类型直接比较值,而引用类型需要比较对应的引用的内存的首地址
2、equals用来比较两个对象长得是否一样,判断两个对象特征是否一样
public class EqualsAnd {
public static void main(String[] args) {
Hello h1 = new Hello(2);
Hello h2 = h1;
Hello h3 = new Hello(4);
System.out.println(h1 == h2); // true
System.out.println(h1 == h3); // false
System.out.println(h1.equals(h2)); // true
System.out.println(h1.equals(h3)); // false
String s = "tom";
System.out.println(s.equals("tom")); // true
System.out.println(s == "tom"); // true
System.out.println(s == new String("tom")); // false
}
}
class Hello{
private int num = 0;
public Hello(int num ){
this.num = num;
// System.out.println(this.num);
}
}
7、String和StringBuilder的区别?StringBuffer和StringBuilder的区别?
1、String是内容不可变的字符串,String底层使用了一个不可变的字符数组
private final char value[];
StringBuilder、StringBuffer是内容可变的字符串,StringBuilder、StringBuffer底层使用的是可变的字符数组,可拼接字符串
2、StringBuilder是线程不安全的(未加同步锁),而效率较高,而StringBuffer是线程安全的(加了同步锁),效率较低
8 、Java中的集合
8.1 分类
value、key-value(Collection和Map两种)
存储值:List、set
存储key-value:map
8.2 List和set区别
1、List是有序的,可重复
2、set是无序的,不可重复,根据equals和hashcode判断
如果一个对象要存储在set中,必须重写equals和hashCode方法
8.3 ArrayList和LinkedList的区别?
List常用的ArrayList和LinkedList?
1、区别:
ArrayList底层使用的是数组
LinkedList底层使用的是链表
数组:优点,查询数据速度快。缺点,插入删除修改比较慢(数组在内存中是一块连续的内存,如果插入删除需要移动内存)
链表:优点,插入删除元素效率高,缺点,查询需要从头部开始找,效率低
8.4 HashMap和HashTable的区别?HashMap和CurrentMap的区别?
1、HashMap和HashTable都可以存储key-value的数据
2、HashMap可以把null作为key或者value的,而HashTable是不可以的
3、HashMap是线程不安全的,效率高。HashTable是线程安全的,效率低。
4、currentHashMap既线程安全又效率高
9、拷贝一个文件的工具类使用的是字节流还是字符流?
我们拷贝的文件不确定是只包含字符流,有可能有字节(图片、声音,图像),为考虑通用性我们使用字符流
10、线程
10.1 线程的实现方式
三种
1、继承Thread
2、实现runable接口
3、实现Callable接口
10.2 有没有使用过线程并发库?
1、JDK5中增加了DougLea的并发库,这一引进给Java线程的管理和使用提供了强大的便利性。
Java.util.current包中提供了对线程优化、管理的各项操作,使得线程的使用变得得心应手
2、Java通过Executors提供四种静态方法创建线程池
(1)newCashedThreadPool
(2)newFixedThreadPool
(3)newScheduledThreadPool
(4)newSingleThreadExecutor
3、线程池的作用:
(1)限定线程的个数,不会导致由于线程过多导致系统运行缓慢或崩溃
(2)线程池在开始不需要每次都去创建或者销毁,节约了资源
(3)线程池不需要每次都去创建,响应时间更快
11、请解释一下对象创建的过程?(半初始化)
1、类构造器完成类初始化(分配内存、赋予默认值) - - - - - - > 半初始化状态
2、类实例化(赋予给定值)
12、加问DCL与volatile问题?(指令重排)
1、DCL单例(Double Check Lock)到底需不需要加Volatile?
指令重排序会导致程序使用半初始化状态对象
13、对象在内存中的存储布局?
14、对象头具体包括什么?
15、对象怎么定位?
16、对象怎么分配?(栈上-线程本地-eden-old)
17、Object o = new Object();在内存中占用多少字节?
16字节
对象头:12 : markword -> 8 class point -> 4
18、设计模式
19.1 单例模式
1、单例模式:保证在内存中产生的对象只有一个
public class Singleton {
/**
* 单例模式例1
*/
private static final Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
public void m() {
System.out.println("m --- ");
}
public static void main(String[] args) {
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
System.out.println(singleton1 == singleton2); // true
}
}
2、单例模式例2
public class Singleton {
/**
* 单例模式例2
*/
private volatile static Singleton INSTANCE;
private Singleton(){}
public static Singleton getInstance(){
if(INSTANCE == null) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Singleton();
}
return INSTANCE;
}
public void m() {
System.out.println("m --- ");
}
public static void main(String[] args) {
for (int i = 0; i < 100 ; i ++) {
new Thread(()->{
System.out.println(Singleton.getInstance().hashCode());
}).start();
}
}
}
3、上述有问题:多线程访问时就不是单例了
解决方式:加锁
public class Singleton {
/**
* 单例模式例3
*/
private volatile static Singleton INSTANCE;
private Singleton(){}
public static synchronized Singleton getInstance(){
if(INSTANCE == null) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Singleton();
}
return INSTANCE;
}
public void m() {
System.out.println("m --- ");
}
public static void main(String[] args) {
for (int i = 0; i < 100 ; i ++) {
new Thread(()->{
System.out.println(Singleton.getInstance().hashCode());
}).start();
}
}
}
4、上述代码中锁太粗了,需要重新加锁
public class Singleton {
/**
* 单例模式例4
*/
private volatile static Singleton INSTANCE;
private Singleton(){}
public static Singleton getInstance(){
if(INSTANCE == null) {
synchronized (Singleton.class){
// if (INSTANCE == null ) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Singleton();
// }
}
}
return INSTANCE;
}
public void m() {
System.out.println("m --- ");
}
public static void main(String[] args) {
for (int i = 0; i < 100 ; i ++) {
new Thread(()->{
System.out.println(Singleton.getInstance().hashCode());
}).start();
}
}
}
5、上述代码优化:双重判断 DCL
public class Singleton {
/**
* 单例模式例5
*/
private volatile static Singleton INSTANCE;
private Singleton(){}
public static Singleton getInstance(){
if(INSTANCE == null) {
synchronized (Singleton.class){
if (INSTANCE == null ) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
public void m() {
System.out.println("m --- ");
}
public static void main(String[] args) {
for (int i = 0; i < 100 ; i ++) {
new Thread(()->{
System.out.println(Singleton.getInstance().hashCode());
}).start();
}
}
}