Java面试整理——Java基础部分

1.一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制

可以有多个类。但是只能有一个public的类,并且public的类名必须和文件名一致。

2. &和&&的区别

  • &和&&都可以用作逻辑与的运算符
  • &&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式。
  • &还可以作位运算符

3. switch 语句能否作用在 byte 上,能否作用在 long 上,能否作用在 String 上?

在switch(expr1)中,expr1只能是一个整数表达式或者枚举常量(更大字体),整数表达式可以时int类型或者integer包装类型,由于,byte,short,char都可以隐含转化为int,所以,这些类型以及这些类型的包装类都是可以的。显然,long和String类型都不符合switch的语法规定,并且不能被隐式转化为int类型,随意他们不能作用于switch语句中。

4. short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?

对于 short s1 = 1; s1 = s1 + 1;由于 s1+1运算时会自动提升表达式的类型,所以结果是 int 型,再赋值给 short 类型 s1时,编译器将报告需要强制转换类型的错误。 对于 short s1 = 1; s1 += 1;由于 +=是 java 语言规定的运算符,java 编译器会对它进行特殊 处理,因此可以正确编译

5. char 型变量中能不能存贮一个中文汉字?为什么?

char型变量是用来存储Unicode编码的字符的,Unicode的编码字符集中包含了汉字,所以char型变量中当然可以存储汉字了。补充说明:Unicode编码占用两个字节,所以char类型的变量也是占用两个字节

6. 用最有效率的方法算出 2 乘以8 等于几?

2 <<3.
将2向左移动三位

7. 使用 final 关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?

使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指的对象中的内容还是可以变得。
例如,对于如下语句:
final StringBuffer a=new StringBuffer(“immutable”);
执行如下语句将报告编译期错误:
a=new StringBuffer("");
但是,执行如下语句则可以通过编译:
a.append(" broken!");

8. "=="和 equals 方法究竟有什么区别?

==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中储存的值是否相等,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符.
如果一个变量指向的数据是对象类型的,那么这时候就涉及到了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,
例如 Object 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 和使用 == 会得到同样的结果,如果比较的是两个独立的对象则总返回 false。如果你 编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖 equals 方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的

9. 静态变量和实例变量的区别?

语法定义上的区别静态变量前要加static关键字,而实例变量不用。
在层序运行上的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为 类变量。只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。
总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。

10. 是否可以从一个 static 方法内部发出对非 static方法的调用?

不可以。因为非 static 方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对 象上进行方法调用,而 static 方法调用时不需要创建对象,可以直接调用。也就是说,当一 个 static 方法被调用时,可能还没有创建任何实例对象,如果从一个 static 方法中发出对非 static 方法的调用,那个非 static 方法是关联到哪个对象上的呢?这个逻辑无法成立,所以, 一个 static 方法内部发出对非 static 方法的调用。

11. Integer 与 int 的区别

int是Java提供的八种原始数据之一,Java为每个原始数据都提供了封装类,integer就是Java为int提供的封装类。int的默认是0,而integer的默认值是null,即integer可以区分出为赋值和值为0的区别,int则无法表达出为赋值的情况。

12. Overload 和 Override 的区别。Overloaded 的方法是否可以改变返回值 的类型?

Overload 是重载的意思,Override 是覆盖的意思,也就是重写。
重载 Overload 表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相 同(即参数个数或类型不同)。
重写 Override 表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子 类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那
个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。子类覆盖父类的方
法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可以解
决父类的一些问题,不能比父类有更多的问题。子类方法的访问权限只能比父类的更大,不 能更小。如果父类的方法是 private 类型,那么,子类则不存在覆盖的限制,相当于子类中 增加了一个全新的方法。
至于 Overloaded 的方法是否可以改变返回值的类型这个问题,要看你倒底想问什么呢?这 个题目很模糊。如果几个 Overloaded 的方法的参数列表不一样,它们的返回者类型当然也 可以不一样。但我估计你想问的问题是:如果两个方法的参数列表完全一样,是否可以让它 们的返回值不同来实现重载 Overload。这是不行的,我们可以用反证法来说明这个问题, 因为我们有时候调用一个方法时也可以不定义返回结果变量,即不要关心其返回结果,例如, 我们调用 map.remove(key)方法时,虽然 remove 方法有返回值,但是我们通常都不会定义 接收返回结果的变量,这时候假设该类中有两个名称和参数列表完全相同的方法,仅仅是返 回类型不同,java 就无法确定编程者倒底是想调用哪个方法了,因为它无法通过返回结果 类型来判断。

override 可以翻译为覆盖,从字面就可以知道,它是覆盖了一个方法并且对其重写,以求达 到不同的作用。对我们来说最熟悉的覆盖就是对接口方法的实现,在接口中一般只是对方法
进行了声明,而我们在实现时,就需要实现接口声明的所有方法。除了这个典型的用法以外, 我们在继承中也可能会在子类覆盖父类中的方法。在覆盖要注意以下的几点:
1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;
2、覆盖的方法的返回值必须和被覆盖的方法的返回一致;
3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;
4、被覆盖的方法不能为 private,否则在其子类中只是新定义了一个方法,并没有对其进行 覆盖

overload 对我们来说可能比较熟悉,可以翻译为重载,它是指我们可以定义一些名称相同 的方法,通过定义不同的输入参数来区分这些方法,然后再调用时,VM就会根据不同的参
数样式,来选择合适的方法执行。在使用重载要注意以下的几点:
1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不 同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是 fun(int,float), 但是不能为 fun(int,int));
2、不能通过访问权限、返回类型、抛出的异常进行重载;
3、方法的异常类型和数目不会对重载造成影响;
4、对于继承来说,如果某一方法在父类中是访问权限是 priavte,那么就不能在子类对其进 行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果

13. 构造器 Constructor 是否可被 override?

构造器 Constructor不能被继承,因此不能重写 Override ,但可以被重载 Overload 。

14. 接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可 继承具体类(concrete class)?抽象类中是否可以有静态的 main方法?

接口可以继承接口。抽象类可以实现(implements)接口,抽象类可以继承具体类。抽象类中 可以有静态的 main 方法。
只有记住抽象类与普通类的唯一区别:就是不能创建实例对象和允许有 abstract 方法。

14. java中实习多态的机制是什么?

靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,

15. abstract的method是否可同时是static

abstract 的 method 不可以是 static 的,因为抽象的方法是要被子类实现的,而 static 与子 类扯不上关系!

16. 内部类可以引用它的包含类的成员吗?有没有什么限制?

完全可以,没有限制。除了静态内部类,静态内部类不可以访问外部类的成员

17. String 是最基本的数据类型吗?

基本数据类型包括byte、int、char、long、float、double、boolean和short。
java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应使用StringBuffer类

18. String s = “Hello”;s = s + " world!";这两行代码执行后,原始的 String 对象中的内容到底变了没有?

没有。因为 String 被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。在 这段代码中,s 原先指向一个 String 对象,内容是 “Hello”,然后我们对 s 进行了+操作,那 么 s 所指向的那个对象是否发生了改变呢?答案是没有。这时,s 不指向原来那个对象了, 而指向了另一个 String 对象,内容为"Hello world!",原来那个对象还存在于内存之中,只 是 s 这个引用变量不再指向它了。

为什么要把 String 类设计成不可变类,是它的用途决定的。其实不只 String,很多 Java 标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的 状态都要一个对象来代表,可能会造成性能上的问题。所以 Java 标准类库还提供了一个可 变版本,即 StringBuffer。

19. 是否可以继承 String 类?

String 类是 final 类故不可以继承。

20. String 和 StringBuffer 的区别

String 和 StringBuffer,它们可以储存和操作字符串,
String不可修改,StringBuffer可修改。
另外String 实现了 equals 方法,new String(“abc”).equals(newString(“abc”)的结果为true,而StringBuffer没有实现equals方法, 所以,new StringBuffer(“abc”).equals(newStringBuffer(“abc”)的结果为 false。
举一个具体的例子,我们要把1到100的所有数字拼起来,组成一个串。

StringBuffer sbf = new StringBuffer();
for(int i=0;i<100;i++){
	sbf.append(i);
}

上面的代码效率很高,因为只创建了一个StringBuffer对象,而下面的代码效率很低,因为创建了101个对象。

String str = new String();
for(int i=0;i<100;i++){
	str = str + i;
}

21. 如何把一段逗号分割的字符串转换成一个数组?

  1. 用正则表达式,代码大概为:String[] result = orgStr.split(",");
  2. 用StringTokenizer,代码为:
StringTokenizer tokener = StringTokenizer(orgStr,",");
String[] result = new String[tokener,countTokens()];
int i = 0;
while(tokener.hasNext(){
	result[i++]=token.nextToken();
}

22. 数组有没有 length()这个方法? String有没有 length()这个方法?

数组没有length()这个方法,有length这个属性。String有length()这个方法

23. 下面这条语句一共创建了多少个对象:String s=“a”+“b”+“c”+“d”;

先看下面这段代码;

String s1 = "a"; 
String s2 = s1 + "b"; 
String s3 = "a" + "b"; 
System.out.println(s2 == "ab"); 
System.out.println(s3 == "ab"); 

第一条语句打印的结果为 false,第二条语句打印的结果为 true,这说明 javac 编译可以对 字符串常量直接相加的表达式进行优化,不必要等到运行期去进行加法运算处理,而是在编 译时去掉其中的加号,直接将其编译成一个这些常量相连的结果
题目中的第一行代码被编译器在编译时优化后,相当于直接定义了一个”abcd”的字符串, 所以,上面的代码应该只创建了一个 String 对象。写如下两行代码

String s = "a"+"b"+"c"+"d";
System.out.println(s=="abdc");

最终打印的结果应该为 true

24. try {}里有一个return 语句,那么紧跟在这个 try后的 finally {}里的 code 会不会被执行,什么时候被执行,在 return 前还是后?

答案看着像是在 return 之前,但往更细地说,我的答案是在 return 中间执行。

参考

25. final, finally, finalize 的区别。

final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 内部类要访问局部变量,局部变量必须定义成 final 类型,例如,一段代码…… finally 是异常处理语句结构的一部分,表示总是执行。 finalize 是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可 以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM 不保证此方法总被 调用

26. 运行时异常与一般异常有何异同?

异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能 遇到的异常,是一种常见运行错误。java 编译器要求方法必须声明抛出可能发生的非运行 时异常,但是并不要求必须声明抛出未被捕获的运行时异常。

27. error 和 exception 有什么区别?

error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指 望程序能处理这样的情况。 exception 表示一种设计或实现问题。也就是说,它表示如果程 序运行正常,从不会发生的情况。

参考

28. 请写出你最常见到的 5 个 runtime exception。

NullPointerException,
ArrayIndexOutOfBoundsException,
ClassCastException

29. 同步和异步有何异同,在什么情况下分别使用他们?举例说明。

如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数 据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。
当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方 法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率

30. 当一个线程进入一个对象的一个 synchronized 方法后,其它线程是否可 进入此对象的其它方法?

分几种情况:

  1. 其他方法前是否加了 synchronized 关键字,如果没加,则能。
  2. 如果这个方法内部调用了 wait,则可以进入其他 synchronized 方法。
  3. 如果其他个方法都加了 synchronized 关键字,并且内部没有调用 wait,则不能。
  4. 如果其他方法是 static,它用的同步锁是当前类的字节码,与非静态的方法不能同 步,因为非静态的方法用的是 this。

31. 线程的基本概念、线程的基本状态以及状态之间的关系

每个程序都至少有一个线程(main方法的那个)。如果只是一个cpu,是怎么同时执行多段程序?,cpu一会执行a线程,一会执行b线程。
状态:就绪,运行,synchronized 阻塞,wait和sleep挂起,结束。wait必须在synchronized内部调用。
调用线程的start方法后,线程进入就绪状态,系统调度后改为运行状态,遇到synchronized转为阻塞,当synchronized获得锁后转为运行。在这种情况下调用wait可以转为挂起。程序执行完后转为结束。

32. 说出 ArrayList,Vector, LinkedList 的存储性能和特性

ArrayList和Vector都是使用数组来存储,索引数据快而插入数据慢,Vector使用了synchronized故线程安全,性能上较ArrayList差。LinkedList使用双向链表存储数据(也是线程不安全),插入数据快索引慢。

33.栈和堆有什么区别

Java内存有两类,一个是栈内存,一个是堆内存。

  • 栈内存:程序进入到一个方法时,会为这个方法分配空间用来存储这个方法内部的局部变量,当这个方法结束时,其分配的空间也会释放,栈中为其分配的变量也随之释放。
  • 堆内存:一般用于存放不放在当前方法栈中的哪些数据,例如,使用new创建的对象都放在堆中,所以它不会因为方法的结束而消失,但如果方法中的变量使用final修饰后,它会被放在堆里而不是栈里

34. 图解HTTP协议

参考

35. 图解tcp的三次握手和四次挥手

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值