1. JAVA中的几种基本数据类型是什么,各自占用多少字节?
8种基本数据类型以及取值范围
byte(1byte字节) -2^7 — 2^7-1
char(2byte) 0 — 2^16-1
short(2byte) -2^15 — 2^15-1
int (4byte)-2^31 — 2^31-1
long(8byte)-2^63 — 2^63-1
float(4byte)-2^31 — 2^31-1
double(8byte)-2^63 — 2^63-1
boolean(1bit比特)true\false
2.java的优点
- 跨平台性(一次编写,到处运行)
- 纯面向对象
- 提供了很多内置的类库
- 提供了对web应用开发的支持
- 具有较好的安全性和健壮性
- 支持多线程
- 简单,去除了C++的指针操作等
3. java的运行原理
java源码首先被编译成字节码文件,再由不同平台的JVM进行解析,java语言在不同平台运行时不需要进行重新编译,JVM在执行字节码文件时,把字节码转换成具体平台的机器指令。
为什么JVM不直接把源码解析成机器码去执行?
- 准备工作:每次执行都需要进行各种检查
- 兼容性:也可以将别的语言解析成字节码
4. jdk 和 jre
jdk:(Java Development Kit)java开发工具包
包括java的运行环境(jre)和java工具,java基础类库
jre:(Java Runtime Environment)java运行环境
包含jvm和java核心类库
5. static是什么?java中是否可以覆盖一个private方法或static方法?
- static是静态的意思,用来修饰成员变量和成员方法,被static修饰的成员方法只能访问静态成员,不能访问非静态成员(需new对象才可以访问)。static是随着类的加载而加载的,因此可以直接用类进行访问。
- 覆盖又为重写(override),重写的前提是继承,private不支持继承,因此被私有的方法不能被重写。
- static是编译时静态绑定的,override是运行时动态绑定的,形式上static是可以override,但实际上不能被override。
6. 重写和重载
重写:不同的类,子类继承父类,子类定义了一个与父类一样的方法(方法名,参数一样),子类去实现这个方法,叫做重写。
重载:同一个类中,多个方法名相同,但是参数类型,参数个数不同。
7.是否可以静态环境中访问非静态变量?
不可以。因为static变量是属于类的,在类加载的时候就被初始化了,这时候非静态变量并没有加载。调用非静态变量是需要实例化(new),类的加载是优先于实例的创建(new)。
8. 什么是自动装箱?
自动装箱:基本数据类型转化为对象包装类型。int --> Integer
自动拆箱:对象包装类型转化为基本数据类型。Integer --> int
为什么需要包装类?
因为java是一种面向对象语言,很多地方都需要使用对象而不是基本数据类型。
为什么要进行转换?
因为在集合(collection)中,只可以存对象,不可以存基本数据类型。
9. java中,什么是构造方法?什么是构造方法重载?什么是复制构造方法?
- 当新对象被创建(new)的时候,构造方法就会被调用,每一个类中都有构造方法,如果该类中没有提供构造方法,java编译器会为这个类创建一个默认的构造方法。
- 构造方法重载和方法重载相似,可以为一个类创建多个构造方法,每一个构造方法必须有它唯一的参数列表。
- java不支持方法的复制,复制构造方法是C++的内容
10.java支持多继承吗?
java中类不支持多继承,只支持单继承(一个子类只有一个父类)
但是java中的接口支持多继承,即一个子接口可以有很多个父接口。
(接口:用来扩展对象的功能,一个子接口继承多个父接口,说明子接口扩展了多个功能,当类实现接口时,类就扩展了相应的功能)
11.接口和抽象类的区别?
- 方法上的区别:
(1)接口中所有的方法默认是抽象的(abstract),隐式抽象;而抽象类中可以同时包含抽象方法和非抽象方法
(2)接口中的方法默认是public;而抽象类中的方法可以是public,private,protected - 类
(1)类可以实现很多个接口(接口多继承);但只能继承一个抽象类(类单继承)
(2)一个类去实现接口,必须实现这个接口中的所有方法;而一个子类去继承抽象类,必须实现它的所有抽象方法,否则这个子类也是抽象类 - 变量
接口中的变量默认是final,而抽象类中的变量包含final和非final
12.值传递和引用传递
- 值传递:基本数据类型传值,对形参的改变,不会影响实参的值
- 引用传递:形参和实参都指向同一个内存地址(同一个对象),所以对参数的改变会影响到实际的对象;引用传递传递的是引用的地址(变量所对应的内存空间的地址)
13. 线程和进程之间的区别
- 根本区别:进程是资源分配的最小单位,线程是程序执行的最小单位
- 在开销方面:每个进程都有自己独立的代码和数据空间,程序之间的切换会有很大的开销;线程可以看做轻量级的进程,线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
- 所处环境:在操作系统中能同时运行多个进程(程序);而同一个进程(程序)中能有多个线程同时执行
- 内存分配:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU之外,系统不会为线程分配内存,线程所使用的资源来自其所属进程的资源,线程组之间只能共享资源。
14.创建线程的方式
- 继承Thread类
- 实现 Runnable 接口
- 实现 Callable 接口
- 使用Executor框架来创建线程池
实现Runnable接口比较受欢迎,因为不需要继承 Thread 类,java类不支持多继承,而java的接口支持多继承。
同时,线程池也是非常高效的,很容易实现和使用。
15.线程的状态
- 新生态(new):新创建一个线程对象。
- 就绪态(Runnable):该状态的线程处于线程池中。等待被线程调度选中,获取CPU的使用权。
- 运行态(Running):可运行状态(就绪态)的线程获取了CPU时间片,执行程序代码。
- 阻塞态(Block):阻塞状态的线程因为某种原因放弃了CPU使用权,让出了CPU时间片。直到线程进入就绪态,才有机会再次获取CPU时间片。
-
死亡态(Dead):死亡的线程不可再次复生,不能调用start()。
线程状态.png
16.同步跟异步
- 同步
当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法(做完一件事后做另一件事)
当客户端发送请求给服务器时,在等待服务器响应的请求时,客户端不做其他事情,当服务端做完了才返回到客户端,客户端一直需要等待,用户使用很不友好。 - 异步
当一个方法被调时不用立刻返回,调用者可以继续后续工作。(同时进行多个事情)
当客户端发送请求给服务端时,在等待服务端响应的时候,客户端可以做其他的事情,节约时间,提高效率。
17.多线程
1. 为什么会出现线程不安全?
当多个线程并发访问同一个共享资源对象时,可能会出现线程不安全的问题。
2. 线程安全
多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能访问直到该线程读取完,其他线程才能使用。
3. 线程不安全
多线程访问时,不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。
4.解决办法:线程同步(synchronized)
java允许多线程并发,当多个线程同时操作一个可共享资源变量时,会导致数据不准确,所以加入同步锁(synchronized)以避免该线程在没有完成操作前被其他线程调用,从而保证该变量的唯一性和准确性。
5.synchronized锁什么?
锁的是对象。临界资源,this当前对象,Class类对象
18.java集合类
1.List接口
List接口扩展自Collection,定义一个允许重复的有序集合。ArrayList和LinkedList的List接口的两个实现类。
(1)ArrayList
动态数组,存储元素,随机查找速度快
(2)LinkedList
链表,插入和删除元素效率高
2.Set接口
Set接口扩展自Collection,不包含重复元素。Set接口有三个具体实现类,分别是散列集HashSet、链式散列集LinkedHashSet和树形集TreeSet。
3.Map接口
19.Array和ArrayList的区别
- Array可以容纳基本数据类型和对象,而ArrayList只能容纳对象
- Array是指定大小的,而ArrayList大小是动态变化的
- ArrayList提供了更多的方法和特性
20.ArrayList和LinkedList
相同:
都实现了List接口和Collection
不同点:
- ArrayList的基于数组实现的;LinkedList是基于链表实现的
- ArrayList随机查找速度快;LinkedList插入和删除速度快
21.为什么要用HashMap?
- HashMap是一个散列桶(数组和链表),它存储的是键值对(key-value)
- HashMap采用了数组和链表的数据结构,在查询和修改方便继承了数组的线程查找和链表的寻址修改
- HashMap是非synchronized,所以HashMap很快
- HashMap 可以接受null键和值,而HashTable不能
22.HashMap的工作原理
HashMap是基于hashing的原理,我们使用put(key,value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法来计算hashcode,然后找到bucket位置来存储值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap()使用链表来解决碰撞问题,当发生碰撞了,对象将会存储在链表的下一个节点中。HashMap在每个链表节点中存储键值对对象。
HashMap之所以在每个数组元素存储的是一个链表,是为了解决hash冲突问题,当两个对象的hash值相等时,一个位置肯定放不下两个值的,于是hashmap采用链表来解决这种冲突,hash值相等的两个元素会形成一个链表。
23.java中==与equals的区别
- “==”的作用是判断两个对象的地址是否相等,即判断两个对象是不是同一个对象(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)
- equals()方法:也是判断两个对象是否相等,但它有两种使用情况:
(1)类没有覆盖equals()方法,则通过equals()比较该类的两个对象时,等价于通过“==”比较这两个对象
(2)类覆盖了equals()方法,这时候比较的是两个对象的内容是否相等
24. hashCode()和equals()
- hashCode()的作用是获取哈希码,也称为散列码,实际上返回的是一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。
- 如果两个对象equals()相等,那么这两个对象一定相等
- 如果两个对象有相同的hashcode,它们的equals()不一定相等
25.java的四种引用,强弱软虚
- 强引用:如果一个对象具有强引用,它就不会被垃圾回收器回收。及时当前内存空间不足,JVM也不会回收它。
- 软引用:在使用软引用时,如果内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收,如果内存不足时,软引用才会被回收。
- 弱引用:当JVM进行垃圾回收时,一旦发现弱引用,无论当前内存空间是否充足,都会被垃圾回收器回收。
- 虚引用:如果一个对象具有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收。
26.final、finally与finalize的区别
- final用于声明属性、方法和类,分别表示属性不可变、方法不可覆盖(重写)、类不可被继承(不能派生出子类)
- finally作为异常处理的一部分,它只能用在try/catch语句中,并且附带一个语句块,表示这段语句最终一定会被执行。finally用法特殊,会撤销之前的return语句,继续执行最后finally中的return语句。
- finalize()是Object类的一个方法,在垃圾回收器执行时会调用被回收对象的finalize()方法,可以覆盖此方法来实现对其他资源的回收。
一旦垃圾回收器准备好释放对象占用的空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。
27. 修饰符的访问权限
- public:可以被任何类访问
- protected:可以被同一包中的所有类访问,可以被所有子类访问(子类没有在同一包中也可以访问)
- private:只能被当前类的方法访问
- 缺省,无访问修饰符:可以被同一包中的所有类访问(如果子类没有在同一包中,也不能访问)
28.java中操作字符串的类有String、StringBuffer和StringBuilder,它们之间有什么区别?
- String 和 StringBuffer、StringBuilder的区别是String是不可变的对象,每次操作都会生成新的String对象,然后引用指向新的String对象;而StringBuffer和StringBuilder是可变的,可以在原有对象的基础上进行操作。
- StringBuffer和StringBuilder的最大区别在于,StringBuffer是线程安全的,而StringBuilder是非线程安全的,单StringBuilder的性能是高于StringBuffer的,所以在单线程的情况下,是推荐使用StringBuilder的,多线程环境下推荐使用StringBuffer。
29.如何将字符串反转?
使用StringBuffer或者SringBuiler的reverse()方法
String str = "abcdef";
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(str);
System.out.println(stringBuffer.reverse());
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(str);
System.out.println(stringBuilder.reverse());
30.抽象类能使用final修饰吗?
不能。定义抽象类就是让其他类继承的,如果定义为final,该类就不能被继承,这样彼此就会产生矛盾,所以final不能修饰抽象类。