Java基础语法面试题50题整理(带答案)
25.Java 中是否可以重写(override)一个 private 或者是static 的方法?
26、什么是内部类?Static Nested Class 和 Inner Class 的不同是啥?
27、JAVA 语言如何进行异常处理,关键字:throws,throw,try,catch,finally分 别代表什么意义?在 try块中可以抛出异常吗?异常有啥用了?
28,java的异常机制有那三种,分别谈谈你的认识:
29,short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 +=1;有什么错?
30,ArrayList 与 LinkedList 区别 ?
31.Vetor arraylist Linkedlist 区别 ?
32,Collection 和 Collections 的区别?。
33、 HashMap 和 Hashtable 的区别。
34、 常见的 runtime exception 有哪些
35,数组(Array)和列表(ArrayList)有什么区别?什么时候应该使用 Array 而不是 ArrayList?
36 Object类是一个特殊的类,是所有类的父类,有什么方法 ?
37,下面的程序代码输出的结果是多少?
public class Test {
public static void main(String[] args) {
System.out.println(new Test().test());
}
int test() {
try {
return func1();
}finally{
return func2();
}
}
int func1() {
System.out.println("func1");
return 1;
}
int func2() {
System.out.println("func2");
return 2;
}
38,单例模式了解吗?来给我手写一下!写一个线程安全的。
39,接口和抽象类的区别是什么 ?
40,java 中实现多态的机制是什么?
41,下列程序输出啥?
public class Test {
public static void main(String[] args) {
System.out.println(new Test().test());
}
static int test() {
int x = 1;
try {
return x;
}finally {
++x;
}
}
}
42,instanceof操作符是用来看啥的?有哪些应用场景?instanceof允许存在泛型参数吗?
43,Java的泛型是类型擦除的是什么意思?
44,可以初始化泛型参数和数组吗?
45,谈谈你对泛型中泛型通配符即extends和super 的认识?
46.集合库框架的继承关系?
47,那你知不知道this和super为啥不能写在静态方法中呢?
String string = new String("string");
String strings = "string";
48,这两行代码创建了几个对象?
0,3
1,可以有多个类,但只能有一个 public 的类,并且 public 的类名必须与文件名相一致。
2,java 中的保留字,现在没有在 java 中使用。
3,&和&&都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都 为 true 时,整个运算结果才为 true,否则,只要有一方为 false,则结果为 false。 &&还具有短路的功能,即如果第一个表达式为 false,则不再计算第二个表达式,
例如,对 于 if(str != null&& !str.equals(“”))表达式,当 str 为 null 时,后面的表达式不会执行,所以不 会出现 NullPointerException 如果将&&改为&,则会抛出 NullPointerException 异常。 If(x==33 &++y>0) y 会增长,If(x==33 && ++y>0)不会增长 &还可以用作位运算符,当&操作符两边的表达式不是 boolean 类型时,&表示按位与操作,
4,两种方法,标签加break ,外层的循环条件表达式的结果可以受到里 层循环体代码的控制
方法一 ok:for (int i = 0; i < 10; i++){ for (int j = 0; j < 10; j++){ if (j == 3) break ok; } } 方法二 boolean boo = true; for (int i = 0; i < 10&&boo; i++){ for (int j = 0; j < 10; j++){ if (j == 3) { boo=false; break ; } } }
5,①装箱:指将基本类型数据值转换成对应的封装对象,即将栈中的数据封装成对象存放到堆栈中;
②拆箱:拆箱是装箱的反过程,是封装的对象转换成基本类型的数据值,即将堆中的数据值存放到栈中的过程。
装箱:Integer integer = Integer.valueOf(12);
拆箱:int i = integer.intValue();
//jdk1.5之后自动调用
Integer integer1 = 12;
int i1 = integer;
6,在 switch(expr1)中,jdk1.7以前,expr1只能是一个整数表达式或者枚举常量(更大字体),整数表达 式可以是 int 基本类型或 Integer 包装类型,由于,byte,short,char 都可以隐含转换为 int,所以,这些类型以及这些类型的包装类型也是可以的。显然,long 和 String 类型都不符合 switch 的语法规定,并且不能被隐式转换成 int 类型,所以,它们不能作用于 swtich 语句中。在jdk1.7后,整形,枚举类型,boolean,字符串都可以。
7,char 型变量是用来存储 Unicode 编码的字符的,unicode 编码字符集中包含了汉字,所以, char 型变量中当然可以存储汉字啦。:unicode 编 码占用两个字节,所以,char 类型的变量也是占用两个字节
8,数值型的初始值为0;布尔型的初始值为false;字符型的为‘\0’(字符串结束标识);引用类型的则为NULL(空引用)字符串String就属于引用类型;
9,2 << 3, 因为将一个数左移 n 位,就相当于乘以了2的 n 次方,那么,一个数乘以8只要将其左移3位 即可,而位运算 cpu 直接支持的,效 率最高,所以,2乘以8等於几的最效率的方法是2 << 3。
10,
将字符串的值转换为基本类型的方法:
直接利用封装类的构造方法,即Xxx(String s)例:int num1=new Integer("12");
调用封装类提供的int num =Integer.paresXxx("123");
将基本类型的值转换为字符串:
直接使用一个空字符串来连接数值即可,String as=" "+as;
调用封装类提供的toString()静态方法,String as=Integer.toString( 100);
调用String类提供的valueOf()静态方法,String as=String.valueOf(45);
11,
==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存 储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作 符。
如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块 内存(堆内存),变量名也占用一块内存(java虚拟机栈),例如 Objet obj = new Object();变量 obj 是一个内存, new Object()是另一个内存,此时,变量 obj 所对应的内存中存储的数值就是对象占用的那 块内存的首地址。如果要比较两个变量是否指向同一个对象,这时候就需要用==操作符进行比较。
equals 方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相 同,它比较的两个对象是独立的。例如,对于下面的代码: String a=new String("foo"); String b=new String("foo"); 两条 new 语句创建了两个对象,然后用 a/b 这两个变量分别指向了其中一个对象,这是两 个不同的对象,它们的首地址是不同的,即 a 和 b 中存储的数值是不相同的,所以,表达 式 a==b 将返回 false,而这两个对象中的内容是相同的,所以,表达式 a.equals(b)将返回 true。
记住,字符串的比较基本上都 是使用 equals 方法。 如果一个类没有自己定义 equals 方法,那么它将继承 Object 类的 equals 方法,Object 类 的 equals 方法的实现代码如下: boolean equals(Object o){ return this==o; } 这说明,如果一个类没有自己定义 equals 方法,它默认的 equals 方法(从 Object类继承 的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用 equals 和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回 false。
12
使用 final 关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容 还是可以改变的。例如,对于如下语句:改变引用变量时报错。
13
,不可以。因为非 static 方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对 象上进行方法调用,而 static 方法调用时不需要创建对象,可以直接调用。也就是说,当一 个 static 方法被调用时,可能还没有创建任何实例对象,如果从一个 static 方法中发出对非 static 方法的调用,那个非 static 方法是关联到哪个对象上的呢?这个逻辑无法成立,所以, 一个 static 方法内部发出对非 static 方法的调用。
14,
false
true
装箱生成的对象,装箱动作通过valueOf实现的,整型池容纳-128—127之间的Integer对象,不在该范围的int类型通过new生成包装对象。即-128这个数字的包装每次都是同一个对象,而128不是同一个对象。整形池存在不仅提高了系统性能,节约内存空间。
15,
Math 类中提供了三个与取整有关的方法:ceil、floor、round,这些方法的作用与它们的英 文名称的含义相对应,例如,ceil 的英文意义是天花板,该方法就表示向上取整, Math.ceil(11.3)的结果为12,Math.ceil(-11.3)的结果是-11;floor 的英文意义是地板,该方法 就表示向下取整,Math.ceil(11.6)的结果为11,Math.ceil(-11.6)的结果是-12;最难掌握的是 round 方法,它表示“四舍五入”,算法为 Math.floor(x+0.5),即将原来的数字加上0.5后再向 下取整,所以,Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。
16,
构造器 Constructor不能被继承,因此不能重写 Override ,但可以被重载 Overload 。
17
接口可以继承接口。抽象类可以实现(implements)接口,抽象类可以继承具体类。抽象类中 可以有静态的 main 方法
18,
Overload 是重载的意思,Override 是覆盖的意思,也就是重写。
重载 Overload 表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相 同(即参数个数或类型,顺序不同)
1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不 同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是 fun(int,float), 但是不能为 fun(int,int));
2、不能通过访问权限、返回类型、抛出的异常进行重载;
3、方法的异常类型和数目不会对重载造成影响;
4、对于继承来说,如果某一方法在父类中是访问权限是 priavte,那么就不能在子类对其进 行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。
重写 Override 表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子 类创建的实例对象调用这个方法时,将调用子类中的定义方法
1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;
2、覆盖的方法的返回值必须和被覆盖的方法的返回一致;
3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;
4、被覆盖的方法不能为 private,否则在其子类中只是新定义了一个方法,并没有对其进行 覆盖
19,
Stirng和StringBuffer,StringBulider都实现了charSequence接口,String为不可改变量,修改要么创建新的字符串对象,要么返回自己(str.substring(0)),StringBuffer是一个可变字符序列,他与String一样,在内存中的都是一个有序的字符序列,不同点是值可以改变,StringBuilder 与 StringBuffer在性能上基本相同,都为可变字符序列。不同点为StringBuffer为线程安全的,而StringBuilder为线程不安全。
使用场景:String:常量的声明,少量的变量运算。StringBuffer:频繁的字符串运算,多线程(xml,Http解析)。StringBuilder:频繁的字符串运算,单线程(SQL语句拼接)。
20,
10.0
21,A, TT这道题我也不知为啥
22,true false false
23,B
24,AD
25
Java 中不能覆盖private方法,因为private修饰的方法只能在当前类中使用,体现的是封装性,其他子类不能访问当前类的private方法,即也不能实现重写。
Java中静态方法不能被覆盖,方法的覆盖是多态的一种,是基于运行时动态绑定的,而static方法是编译时静态绑定的。Static方法与类的实例没有关系,不体现多态。所以不能实现覆盖,重写的static方法的行为被称为隐藏。
26
内部类就是在一个类的内部定义的类,
java中的嵌套类(Nesetd Class):分为两种,静态内部类(也叫静态嵌套类,Static Nested Class)和内部类(Inner Class),
静态内部类
:加强了类的封装性,提高了代码的可读性。静态内部类不持有外部类的引用(普通内部类可以访问外部类的方法,属性,即使是private类型也可以访问,静态内部类只可以访问外部类的静态方法和静态属性),静态内部类不依赖外部类(普通内部类与外部类之间是相互依赖的关系,) 静态内部类可以独立存在,即使外部类消亡,静态内部类还是可以存在),
内部类:
不能定义静态成员,内部类可以直接访问外部类中的成员变量;内部类可以定义在外部类的方法外面, 也可以定义在外部类的方法体中,
在方法体外面定义的内部类的访问类型可以是 public,protecte,默认的,private 等4种类型, 这就好像类中定义的成员变量有4种访问类型一样
在方法内部定义的内部类前面不能有访问类型修饰符,就好像方法中定义的局部变量一样, 但这种内部类的前面可以使用 final 或 abstract修饰符。这种内部类对其他类是不可见的其 他类无法引用这种内部类
27
首先讲处理异常的机制,Java将异常分为Error和Exception
Error一般是jvm'错误,不可挽回的错误,
excprtion 指程序中出现的异常
分为检查型异常和非检查型异常
检查型异常是指程序必须要处理的异常
非检查型异常是指可以发生异常的异常,不许要强制处理
throws 捕获并向外抛出异常
throw抛出异常
try catch 是内部捕获异常并做自定义处理
finally 是无论是否有异常都会被处理的语句,除非在 finally 前存在被执行的 System.exit(int i)时除外
![](https://img2018.cnblogs.com/i-beta/1424271/202002/1424271-20200203191344946-2121602348.png)
异常的作用:
1,对程序的错误进行统一的封装,当异常发生时,能够告诉编程人员那里有异常,发生了什么异常。
2,可以使本来终断的程序以适当的方式继续运行,或退出,进行后处理数据回滚,资源释放等。
28,
Erroe类及其子类表示为错误,它是不需要程序员处理也不能处理的异常,比如VirtualMachineError虚拟机错误,Thread线程僵死等。
RuntimeException类及其子类表示非受检异常,是系统可能会抛出的异常,编译器不要求强制处理的异常,常见的有NullPointException异常和IndexOutBoundException越界异常,
Exception类及其子类中除RuntimeException异常,表示受检异常,是程序员必须处理的异常,不处理程序不能通过,IOException和SQLException异常。
29,
1) 对于 shorts1=1;s1=s1+1 来说,在s1+1 运算时会自动提升表达式的类型为 int, 那么将int赋予给 short类型的变量 s1会出现类型转换错误。
2) 对于 short s1=1;s1+=1 来说 +=是java 语言规定的运算符,java 编译器会对它 进行特殊处理,因此可以正确编译。
30
ArrayList 和 LinkedList 都实现了 List 接口,他们有以下的不同点:
ArrayList 是基于索引的数据接口,它的底层是数组。它可以以 O(1)时间复杂度对元素进行 随机访问。
LinkedList 是以元素列表的形式存储它的数据,每一个元素都和它的 前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是 O(n)。
相对于 ArrayList,LinkedList 的插入,添加,删除操作速度更快,因为当元素被添加到集合 任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。 LinkedList 比 ArrayList 更占内存,因为 LinkedList 为每一个节点存储了两个引用,一个指 向前一个元素,一个指向下一个元素。
31
ArrayList 就是动态数组,是 Array 的复杂版本,动态的增加和减少元素.当更多的元素 加入到 ArrayList 中时,其大小将会动态地增长。它的元素可以通过 get/set 方法直接访问, 因为 ArrayList 本质上是一个数组。初始容量为 10。
1.插入元素的时候可能扩容,删除元素时不会缩小容量。
2.扩容增长为Arraylist 增长原来的 0.5 倍
3. 而 Arraylist 没有设置增长空间 的方法。
4.线程不同步
Vector 和 ArrayList 类似, 区别在于 Vector 是同步类(synchronized).因此,开销就比 ArrayList 要大。初始容量为 10。
实现了随机访问接口,可以随机访问。Vector 是内部是以动态数组的形式来存储数据的。
1.Vector 还可以设置增长的空间大小,
2. 及 Vector 增长原 来的 1 倍
3.vector 线程同步
LinkedList 是一个双链表,在添加和删除元素时具有比 ArrayList 更好的性能.但在 get 与 set 方面弱于 ArrayList.当然,这些对比都是指数据量很大或者操作很频繁的情况下的对 比。它还实现了 Queue 接口,该接口比 List 提供了更多的方法,包括 offer(),peek(),poll()等.
32,
Collection 是集合类的上级接口,继承与他的接口主要有 Set 和 List。Collections 是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排 序、线程安全化等操作。
33
HashMap 是 Hashtable 的轻量级实现(非线程安全的实现),他们都完成了 Map 接口,主要区别在于 HashMap 允许空(null)键值(key),由于非线程安全,效 率上可能高于 Hashtable。 HashMap 允许将 null 作为一个 entry 的 key 或者 value,而 Hashtable 不允许。 HashMap 把 Hashtable 的contains 方法去掉了,改成 containsvalue 和 containsKey。 因为 contains 方法容易让人引起误解。 Hashtable 继承自 Dictionary 类,而 HashMap 是 Java1.2 引进的 Map interface 的一个实现。 最大的不同是,Hashtable 的方法是 Synchronize 的,而 HashMap 不是,在多个线 程访问 Hashtable 时,不需要自己为它的方法实现同步,而 HashMap 就必须为 之提供外同步。 Hashtable 和 HashMap 采用的 hash/rehash 算法都大概一样,所 以性能不会有很大的差异
34
ClassCastExcetion,NullPointerException,NumberFormatException, OutOfMemoryException,ArrayIndexOfBoundsException
35
答:不同点:定义上:Array 可以包含基本类型和对象类型,ArrayList 只能包含对象类 型。容量上:Array 大小固定,ArrayList 的大小是动态变化的。操作上:ArrayList 提供更多 的方法和特性,如:addAll(),removeAll(),iterator()等等。使用基本数据类型或者知道数 据元素数量的时候可以考虑 Array;ArrayList 处理固定数量的基本类型数据类型时会自动装 箱来减少编码工作量,但是相对较慢。
![](https://img2018.cnblogs.com/i-beta/1424271/202002/1424271-20200203191830053-1669277638.png)
37
func1
func2
2
1
38
懒汉式单例,在第一次调用的时候实例化自己: public class Singleton{ private Singleton(){} private static Singleton single=null; public static Singleton getInstance(){ if(sing==null) single=new Singleton(); return single; }} 静态内部类: public class Singleton{ private static class Lazy{ private static final Singleton INSTANCE=new Singleton();} private Singleton(){} public static final Singleton getInstance(){ return LAZY.INSTANCE; } } 饿汉式单例类,在初始化时,自行实例化。 public class Singletonon1{ private Singleton1(){} private static final Singleton1 single=new Singleton1(); public static Singleton1 getInsttance(){ return single; } 双重校验锁实现对象单例(线程安全): public class Singleton { private volatile static Singleton uniqueInstance; private Singleton() { } public static Singleton getUniqueInstance() { //先判断对象是否已经实例过,没有实例化过才进入加锁代码 if (uniqueInstance == null) { //类对象加锁 synchronized (Singleton.class) { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } } } return uniqueInstance; } }
39
靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方
法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运 行的那个对象的方法,而不是引用变量的类型中定义的方法
40
1. 接口的方法默认是 public,所有方法在接口中不能有实现(Java 8 开始接口方法可以有默认实现),抽象类可以 有非抽象的方法
2. 接口中的实例变量默认是 final 类型的,而抽象类中则不一定
3. 一个类可以实现多个接口,但多只能实现一个抽象类
4. 一个类实现接口的话要实现接口的所有方法,而抽象类实现接口不一定
5. 接口不能用 new 实例化,但可以声明,但是必须引用一个实现该接口的对象 从设计层面来说,抽象是对类的抽 象,是一种模板设计,接口是行为的抽象,是一种行为的规范。
6,在JDK8中,接口也可以定义静态方法,可以直接用接口名调用。实现类和实现是不可以调用的。如果同时实现 两个接口,接口中定义了一样的默认方法,必须重写,不然会报错。(
41
1
42,判断对象类型,
当程序执行向下转型操作的时候,如果父类对象不是子类对象的实例,就会发生异常,所以在执行向下转型之前需要养成一个习惯,利用instanceof判断父类对象是否为子类对象的实例,可以使用instanceof操作判断是否一个类实现了某个接口和一个对象是否属于一个实例。某类对象的引用 instanceof 某个类;返回类型为boolear值。
instanceof不允许存在泛型参数,
"String" instanceof String //返回值为true
new String() instanceof String //返回值为true
new Object() instanceof String //false(可以编译)
'A' instanceof Character //编译不通过,A为基本类型,Character为封装类,前边必须为对象。
null instanceof String //false,特殊规则,如果左操作数是null,结果就直接返回false,不在运运算右操作数,
(String)null instanceof String //false,null是一个万用类型,可以说它没有类型,即使类型转换也是null。
new Date() instanceof String //编译不通过,没有继承实现关系。
T(T为泛型String类变量) instanceof Date; //通过,false,T被编译为Object类,传递String类的值,所以 "Object instanceof Date";
43,
Java泛型(Generic)的引入加强了参数类型的安全性,减少了乐行的转化,Java泛型在编译期有效,在运行期被删除,即泛型参数类型在编译后都会被清除掉。
转化规则:
List< String>,List< Integer>,List擦除后的类型为List
List< String>[],类型擦除后是List[];
List<? extends E>,List<? super E>擦除后的类型为List.
List<T extends Serializable & Cloneable>擦除后为List< Serializable>
44,
不能初始化泛型参数和数组,new T();,new T(5)都不能通过,new ArrayList< T>()可以通过。ArrayList表面是泛型,其实已经在编译期转型为Object了,数组允许协变(Covariant),即可以容纳所有对象,类的成员变量是在类初始化前初始化的,所有要求在初始化前它必须具有明确的类型,否则则就只能申明,不能初始化。
45,
Java泛型支持通配符,可以使用“?”,表示任意类,也可以使用extends 关键字表示某一个类的(接口)的子类型,可以使用super关键字表示某一个类(接口)的父类。
如果一个泛型结构即用作读操作,又用作写操作,使用确切的泛型类型即可。
在泛型结构中,只参与“读”操作则限定上界(extends): public static <E> void read(List<? extends list>) { for( E e:list) { } } 泛型结构只参与"写“操作则限定下界(super)。 public static void write(List<? super Number> lsit){ lsit.add(123); lsit.add(33.14); }
46,
47,涉及到类初始化时的加载顺序,static方法和变量是在类初始化时首先被加载的,即在对象初始化之前就被加载了,是属于类的,即没有对象也可以执行。this表示当前对象,super表示父类对象,描述的是对对象的操作,把this和super放到static方法中不符合逻辑。那时候还没有对象出现。会报空指针异常。,
48, 第一个两个对象,第二个一个对象。