java基础篇
1.JDK与JRE有啥区别?
JDK:java开发工具包,提供了Java的开发环境和运行环境。
JRE:提供了Java的运行所需的环境。
JDK包括了JRE,还包含了其他java需要运行时的编译器javac。
2.= =和equals的区别?
==解读:
1.基本类型:比较值
2.引用类型:比较的事引用值是否相等。
equals:
本质上还是= = 。string,object重写了equals的方法,把它当成了值比较。
默认情况下是引用比较。只是很多类重写了equals方法。
首先来看默认的情况下equals比较有一个相同值对象,代码如下
class Cat {
public Cat(String name) {
this.name = name;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Cat c1 = new Cat("小王");
Cat c2 = new Cat("小王");
System.out.println(c1.equals(c2)); // false
输出结果出乎我们的意料,竟然是 false?这是怎么回事,看了 equals 源码就知道了,源码如下:
public boolean equals(Object obj) {
return (this == obj);
}
原来 equals 本质上就是 ==。
总结 :== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。
3.两个对象的hashcode()相同,则equals()也一定为true?
不对 两个对象的hashcode()相同,equals()不一定true。
String str1 = "通话";
String str2 = "重地";
System.out.println(String.format("str1:%d | str2:%d", str1.hashCode(),str2.hashCode()));
System.out.println(str1.equals(str2));
执行的结果:
str1:1179395 | str2:1179395
false
4.面向对象的特征有哪些方面?
1)封装性:
将对象的状态信息尽可能的隐藏起来,只保留有限的接口和方法来对外界进行交互,从而避免了外界对对象内部属性的破坏。
java中的访问控制符的大小为
public>protected>default>private
2)继承:
java通过继承创建等级层次的类。即一个对象从另外一个独享获取属性的过程。
类的继承是单一的,但可以通过接口进行多继承。通过关键字extend来继承。
3)多态:多态是指一个行为具有多种不同的表现形式或形态的能力。
多态是对象多种表现形式的体现。
5.String是基本数据类型吗?
基本数据数据类型:int double char long float byte short boolean
6.&和&&的区别?
相同点:都可以当做逻辑与的运算符。
不同点:
1.&&具有短路的功能,而&不具备此功能。
2.当&运算符两边的等式都为true,才会为true。而&&运算符的第一个表达式为false,则结果为false。不再计算第二个表达式。
3.&还是当做位运算法。
7.switch是否可以作用在byte?
在java5以前。switch可以作用在byte short char,int。
从java5之后,引入了枚举类型,从java7开始,加入了string。但是long在当前版本还不可以。
8.在java中如何跳出当前循环?
方法一;
public static void main(String[] args) {
System.out.println("标记前");
ok: for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.println("i=" + i + ",j=" + j);
if (j == 5)
break ok;
}
}
System.out.println("标记后");
}
方法二:
使外层的循环的条件遭到破坏 即可跳出控制
public static void main(String[] args) {
System.out.println("标记前");
boolean flag = true;
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10 && flag; j++) {
System.out.println("i=" + i + ",j=" + j);
if (j == 5)
flag = false;
}
}
System.out.println("标记后");
}
9.构造器(constructor)是否可以被重写?
重写发生在子类和父类中,方法名,参数列表,返回值,返回修饰符和异常都相同,首先,构造器不能被破坏,因为每个类名不一样,构造器的名称和类名相同,即这不算继承,所以不能被重写,但可以被重载。
10.String类是否可以被继承?
String类是final修饰的 ,不可被继承。
11.java中操作字符串有哪些类?他们有什么区别?
操作类型的字符串:String ,StringBuffer,StringBuilder.
String和StringBuffer,StringBuilder的区别在于String声明的是不可变的对象,每次操作的都会生成新的String对象,然后将指针指向新的String对象。而StringBuffer和StringBuilder可以在原对象的基础上进行操作,所以经常改变字符串内容的情况下,不要使用String.
Stringbuffer和StringBuilder最大的区别在于,Stringbuffer是线程安全的。而StringBuilder是非线程安全。但stringbuilder的性能却高于stringBuffer 所以在单线程下推荐视同StringBuffer。多线程环境下推荐使用StringBuffer。
**面试题1** - 什么情况下用+运算符进行字符串连接比调用StringBuffer/StringBuilder对象的append方法连接字符串性能更好?
少量的字符串可以使用+
String一旦赋值或实例化后就不可更改,如果赋予新值将会重新开辟内存地址进行存储。
而StringBuffer类使用append和insert等方法改变字符串值时只是在原有对象存储的内存地址上进行连续操作,减少了资源的开销。
如果有大量需要进行字符串拼接的操作,最好还是使用StringBuffer或StringBuilder进行。
面试题2 - 请说出下面程序的输出。
class StringEqualTest {
public static void main(String[] args) {
String s1 = "Programming";
String s2 = new String("Programming");
String s3 = "Program";
String s4 = "ming";
String s5 = "Program" + "ming";
String s6 = s3 + s4;
System.out.println(s1 == s2);
System.out.println(s1 == s5);
System.out.println(s1 == s6);
System.out.println(s1 == s6.intern());
System.out.println(s2 == s2.intern());
}
}
输出结果:
false
true
false
true
false
12.重载(Overload)和重写(override)有什么区别?
重载和重写是在两个不同场景下面的不用手段。
重载:首先是位于一个类之中或者其子类,具有相同的方法名,但是方法的参数不同,返回值类型可以相同也可以不同。
-
方法名必须相同
-
方法的参数列表一定不一样
-
访问修饰符和返回类型可以胸痛也可以不同。
重载是对于不同的情况西而不同的方法。
public class Animal { public void bark(){ System.out.println("animal can bark"); } public void bark(String s){ System.out.println("animal"+ s +"can bark"); } public void bark(int i){ System.out.println("The animal number "+i+" can bark"); } public static void main(String[] args) { Animal animal=new Animal(); animal.bark(1); } }
重写:一半是子类和父类之间的关系。其主要的特征是:方法名相同,参数相同,单数具体的实现不同。
重写的特征:
1.方法名必须相同,返回值必须相同
2.参数列表必须相同
3.访问权限不能比父类中被重写的方法的权限更低
4.如果父类和子类在通报一个包里,那么子类可以重写父类的所有方法,除了声明为private和final的方法
5.构造方法不能重写。
public class Animal {
public void bark() {
System.out.println("animal can bark");
}
}
public class Dog extends Animal {
public void bark() {
System.out.println("Dog can bark");
}
public static void main(String[] args) {
Dog dog = new Dog();
dog.bark();
}
}
13.描述一下JVM加载class文件的原理机制
java中的所有类,都需要由类加载器装载到jvm中才能运行。类加载器本身也是一个类,工作本身就是把class文件从硬盘读取到内存中。
类装载方式,有两种:
1.隐式装载, 程序在运行过程中当碰到通过new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中,
2.显式装载, 通过class.forname()等方法,显式加载需要的类
==Java类的加载是动态的,它并不会一次性将所有类全部加载后再运行,而是保证程序运行的基础类(像是基类)完全加载到jvm中,至于其他类,则在需要的时候才加载。这当然就是为了节省内存开销。==Java的类加载器有三个,对应Java的三种类:
Bootstrap Loader :启动类加载器,是虚拟机自身的一部分。
ExtClassLoader : 负责加载扩展类(就是继承类和实现类)
AppClassLoader :负责加载用户类路径(ClassPath)上所指定的类库(程序员自定义的类)
JVM中类的加载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。
由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。
类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。加载完成后,Class对象还不完整,所以此时的类还不可用。
当类被加载后就进入连接阶段,这一阶段包括
验证:为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
准备:为静态变量分配内存并设置默认的初始值。
解析:将符号引用替换为直接引用。
最后JVM对类进行初始化,包括:
如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;
如果类中存在初始化语句,就依次执行这些初始化语句。
类的加载是由类加载器完成的,类加载器包括:启动类加载器(BootStrap)、扩展类加载器(Extension)、应用程序类加载器(Application)。
双亲委派模型:要求除了顶层的启动类加载器外,其余加载器都应当有自己的父类加载器。类加载器之间的父子关系,一般不会以继承的关系来实现,而是通过组合关系复用父加载器的代码。
工作过程:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成。
每个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,
只有到父加载器反馈自己无法完成这个加载请求(它的搜索范围没有找到所需的类)时,子加载器才会尝试自己去加载。
14、char 型变量中能不能存贮一个中文汉字,为什么?
char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,
所以,char型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在
unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。补充
说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。
15.抽象类(abstrat class)和接口interface有什么异同?
不通点:
- 接口只有方法定义,没有具体的实现,实现接口的类要实现接口的所有方法;抽象类可以有定义与实现
- 接口与类是实现关系,并且类可以多实现。抽象类和类是继承关系。只能单继承。
- 接口中成员全为public
相同点:
- 都不能被实例化
- 都可以将抽象类和接口类型作为引用类型
- 一个类如果实现接口或继承抽象类,必须实现全部抽象方法,否则仍然是个抽象类。
16静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?
Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化
面试题 - 下面的代码哪些地方会产生编译错误?
class Outer {
class Inner {}
public static void foo() { new Inner(); }
public void bar() { new Inner(); }
public static void main(String[] args) {
new Inner();
}
}
注意:Java中非静态内部类对象的创建要依赖其外部类对象,上面的面试题中foo和main方法都是静态方法,静态方法中没有this,也就是说没有所谓的外部类对象,因此无法创建内部类对象,如果要在静态方法中创建内部类对象,可以这样做:
new Outer().new Inner();
17 java中会存在内存泄漏吗?
内存泄漏是指不再使用的对象或者变量一直被占据在内存中。
理论上来说,Java是有Gc回收机制的。
java存在内存泄漏的问题的情况。
1.长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄漏。
18静态变量和实例变量的区别
java中静态变量和实例变量可以统称为成员变量。
静态变量也叫做类变量,独立于方法之外的变量。有static修饰。
实例变量也是独立于方法之外的变量,但没有static修饰。
总结:
实例变量是属于某个对象的属性,必须创建了实例对象。
静态变量不属于某个实例对象,而是属于某个类。
19静态方法是否可以调用非静态方法?
不可以 非静态方法的调用要先调用对象,在调用静态方法时可能对象并没有被实例化。
20 GC是什么?为什么要有GC
GC是垃圾收集的意思。内存处理是编程人员容易出现问题的地方;忘记或者错误的内存回收会导致程序出问题,GC功能可以自动检测对象是否超过作用域从而达到自动回收的目的。
调用下面的方法:System.gc()或Runtime.getTRuntime().gc(),但JVM可以屏蔽掉显示的垃圾回收调用。
垃圾回收可以有效的防止内存泄漏。有效的使用内存。
21 String s=new String(“xyz”)创建了几个字符串对象?
两个对象 一个静态区的xyz 一个是在new创建堆上的对象。
22、接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?
答:接口可以继承接口,而且支持多重继承。抽象类可以实现(implements)接口,抽象类可继承具体类也可以继承抽象类。
23、一个".java"源文件中是否可以包含多个类(不是内部类)?有什么限制?
答:可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致。
24 java中的final关键字有哪些用法?
1.修饰类,表示该类不可被继承
2.修饰方法:表示该方法不能被重写
3.修饰变量:表示变量只能被一次赋值不可被修改
25 指出下面程序的运行结果
class A {
static {
System.out.print("1");
}
public A() {
System.out.print("2");
}
}
class B extends A{
static {
System.out.print("a");
}
public B() {
System.out.print("b");
}
}
public class Hello {
public static void main(String[] args) {
A ab = new B();
ab = new B();
}
}
输出结果:1a2b2b
26 数据类型之间的转换
如何将字符串转换为基本数据类型?
如何将基本数据类型转换为字符串?
- 调用基本数据类型对应的包装类中的parseXXX(String)或Value(String) 即可返回基本类型
- 一种方法是将基本数据类型与空字符串(“”)连接(+)即可获得其所对应的字符串;另一种方法是调用String 类中的valueOf()方法返回相应字符串
27 如何将字符串翻转?
使用StringBuilder 或者Steingbuffer 的reverse()方法
// StringBuffer reverse
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("abcdefg");
System.out.println(stringBuffer.reverse()); // gfedcba
// StringBuilder reverse
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("abcdefg");
System.out.println(stringBuilder.reverse()); // gfedcba
28 比较一下Java 和JavaSciprt
javaScript与java是两个公司的不同的两个产品。java是sun公司的 javascript是Netecape公司的产品,是开发web页面中运行的解释性语言。
异同点:
- 基于对象和面向对象,Java是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象;JavaScript是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。
- 解释和编译:Java的源代码在执行之前,必须经过编译。JavaScript是一种解释性编程语言,其源代码不需经过编译,由浏览器解释执行。
- 强类型变量和类型弱变量:Java采用强类型变量检查,即所有变量在编译之前必须作声明;JavaScript中变量是弱类型的,甚至在使用变量前可以不作声明,JavaScript的解释器在运行时检查推断其数据类型。
29 Error和Exception有什么区别?
都继承于Throwable类,在java中只有Throwable类型实例才可以被抛出或者捕获。
Exception是java程序运行中可预料的异常情况,咱们可以获取到这种异常,并且对这种异常进行业务外的处理。
Error是java程序运行中不可预料的异常情况,这种异常发生以后,会直接导致JVM不可处理或者不可恢复的情况。所以这种异常不可能抓取到,比如OutOfMemoryError、NoClassDefFoundError等。
30try{}里有一个return语句,那么紧跟在这个try后的finally{}里的代码会不会被执行,什么时候被执行,在return前还是后?
答:会执行,在方法返回调用者前执行。
31 列出常见的运行时异常
- java.lang.NullPointerException,这个异常的解释是 "程序遇上了空指针 "
- java.lang.ClassNotFoundException,异常的解释是"指定的类不存在"
- java.lang.ArrayIndexOutOfBoundsException,这个异常的解释是"数组下标越界"
- java.lang.NoSuchMethodError,方法不存在错误
- java.lang.IndexOutOfBoundsException,索引越界异常
- java.lang.NumberFormatException,数字格式异常。
- java.sql.SQLException,Sql语句执行异常
32 阐述final finally finallize的区别
final:修饰符(关键字)有三种用法:如果一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承,因此它和abstract是反义词。将变量声明为final,可以保证它们在使用中不被改变,被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取不可修改。被声明为final的方法也同样只能使用,不能在子类中被重写。
finally:通常放在try…catch…的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放外部资源的代码写在finally块中。
finalize:Object类中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize()方法可以整理系统资源或者执行其他清理工作。
33 List Set Map 是否继承自Collection接口?
List set是 Map不是,Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复的元素,List是线性结构的容器,适用于按数值索引访问元素的情形。
34 ArrayList Vector LinkedList的存储性能和特性
ArrayList 和Vector都是使用数组方式存储数据,它们都允许直接按序号索引元素,索引数据快而插入数据慢。
Vector中的方法由于添加了synchronized修饰,因此Vector是线程安全的容器,但性能上较ArrayList差
35 colleection 和Collections的区别?
Collection是一个接口,他是Set List等容器的接口,Collections是一个工具类,提供了一系类的静态方法来辅助容器操作,这些方法包括对容器的搜索,排序等
36、List、Map、Set三个接口存取元素时,各有什么特点?
List以特定索引来存取元素,可以有重复元素。
Set不能存放重复元素(用对象的equals()方法来区分元素是否重复)。
Map保存键值对(key-value pair)映射,映射关系可以是一对一或多对一。
Set和Map容器都有基于哈希存储和排序树的两种实现版本,基于哈希存储的版本理论存取时间复杂度为O(1),而基于排序树版本的实现在插入或删除元素时会按照元素或元素的键(key)构成排序树从而达到排序和去重的效果。