关于应届生JAVA面试题整理Java基础部分提供一份

关于应届生JAVA面试题整理Java基础部分提供一份

村头老杨头

Sat Apr 18

村头老杨头
垃圾回收的优点和原理。并考虑2种回收机制。

答案:
Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。
由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。

优点:垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。

原理:垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。

回收机制:有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。

GC是什么? 为什么要有GC?

答案:
GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。

final, finally, finalize的区别。

答案:
final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 内部类要访问局部变量,局部变量必须定义成final类型。

finally是异常处理语句结构的一部分,表示总是执行。

finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。

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

答案:
使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。

例如,对于如下语句: final StringBuffer a=new StringBuffer("immutable");

执行如下语句将报告编译期错误: a=new StringBuffer(""); 但是,执行如下语句则可以通过编译: a.append(" broken!");

有人在定义方法的参数时,可能想采用如下形式来阻止方法内部修改传进来的参数对象: public void method(final StringBuffer param){ } 实际上,这是办不到的,在该方法内部仍然可以增加如下代码来修改参数对象: param.append("a");

构造器Constructor是否可被override?

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

面向对象的特征有哪些方面?

答案:
面向对象的三大特征:1.继承 2.封装 3.多态性

(1)继承:就是保留父类的属性,扩展新的东西。通过子类可以实现继承,子类继承父类的所有状态和行为,同时添加自身的状态和行为。

(2)封装:就是类的私有化。将代码及处理数据绑定在一起的一种编程机制,该机制保证程序和数据不受外部干扰。

(3)多态:是允许将父对象设置成为和一个和多个它的子对象相同的技术。包括重载和重写。 重载是同一个类中多态的一种表现形式,重写是父类和子类之间的一种多态的表现形式。

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

答案:
Overload是重载的意思,Override是覆盖的意思,也就是重写。

重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)。它是一个类中多态性的一种表现。返回值类型可以相同也可以不相同,无法以返回型别作为重载函数的区分标准。

重写Override:在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。 若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。 如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。

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

答案:
不可以。

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

error和exception有什么区别?

答案:
error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。

exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。

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

答案:
完全可以。如果不是静态内部类,那没有什么限制!

如果你把静态嵌套类当作内部类的一种特例,那在这种情况下不可以访问外部类的普通成员变量,而只能访问外部类中的静态成员

abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?

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

native方法表示该方法要用另外一种依赖平台的编程语言实现的,不存在着被子类实现的问题,所以,它也不能是抽象的,不能与abstract混用。例如,FileOutputSteam类要硬件打交道,底层的实现用的是操作系统相关的api实现,例如,在windows用c语言实现的,所以,查看jdk 的源代码,可以发现FileOutputStream的open方法的定义如下: private native void open(String name) throws FileNotFoundException; 如果我们要用java调用别人写的c语言函数,我们是无法直接调用的,我们需要按照java的要求写一个c语言的函数,又我们的这个c语言函数去调用别人的c语言函数。由于我们的c语言函数是按java的要求来写的,我们这个c语言函数就可以与java对接上,java那边的对接方式就是定义出与我们这个c函数相对应的方法,java中对应的方法不需要写具体的代码,但需要在前面声明native。

关于synchronized与abstract合用的问题,我觉得也不行,因为在我几年的学习和开发中,从来没见到过这种情况,并且我觉得synchronized应该是作用在一个具体的方法上才有意义。而且,方法上的synchronized同步所使用的同步锁对象是this,而抽象方法上无法确定this是什么。

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

答案:
题目中的代码被编译器在编译时优化后,相当于直接定义了一个”abcd”的字符串,所以,上面的代码只创建了一个String对象。

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

答案:
“==”操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。

equals方法是用于比较两个独立对象的内容是否相同。

扩展: 如果一个类没有自己定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码如下: boolean equals(Object o){ return this==o; } 这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object 类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。

JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?

答案:
throws、throw:这是用于抛出异常,区别在于throw是在语句中抛出、throws是在方法体上抛出,可以抛出多个,用逗号隔开。

try:是将会发生异常的语句括起来,从而进行异常的处理,也可以在try块中抛出新的异常 。

catch:是如果有异常就会执行它里面的语句 。

finally:不论是否有异常都会进行执行的语句。

下面的程序代码输出的结果是多少?
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; 
  }
}

答案:
func1
func2
2

**结论:**finally中的代码在return语句后执行。

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

答案:
NullPointerException
ArrayIndexOutOfBoundsException
ClassCastException
SQLException
FileNotFoundException
IOException

说说Java中的异常处理机制的简单原理和应用?

答案:
异常是指java程序运行时(非编译)所发生的非正常情况或错误。Java使用面向对象的方式来处理异常,它把程序中发生的每个异常都分别封装到一个对象来表示的,该对象中包含有异常的信息。

Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常的根类为java.lang.Throwable,Throwable下面又派生了两个子类:Error和Exception。

Error 表示应用程序本身无法克服和恢复的一种严重问题,程序只有死的份了,例如,说内存溢出和线程死锁等系统问题。

Exception表示程序还能够克服和恢复的问题,其中又分为系统异常和普通异常,系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);

普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。

java为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须try..catch处理或用throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常,而系统异常可以处理也可以不处理,所以,编译器不强制用try..catch处理或用throws声明,所以系统异常也称为unchecked异常。

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

答案:
异常表示程序运行过程中可能出现的非正常状态。

运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。

java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。

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

答案:
char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。

String 和StringBuffer、StringBuilder的区别?

答案:
StringBuffer、StringBuilder和String一样,也用来代表字符串:

String类是不可变类,任何对String的改变都会引发新的String对象的生成;

StringBuffer和StringBuilder则是可变类,任何对它所指代的字符串的改变都不会产生新的对象。

StringBuffer和StringBuilder区别: StringBuffer 线程安全的;StringBuilder 线程非安全的。

三者在执行速度方面的比较:StringBuilder > StringBuffer > String

java中实现多态的机制是什么?

答案:
靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。

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

答案:
2 << 3, 因为将一个数左移n位,就相当于乘以了2的n次方,那么,一个数乘以8只要将其左移3位即可,而位运算cpu直接支持的,效率最高,所以,2乘以8等於几的最效率的方法是2 << 3。

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

答案:
没有。因为String被设计成不可变的类,所以它的所有对象都是不可变对象。

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

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

答案:
基本数据类型包括byte、int、char、long、float、double、boolean和short。 所有String类不是基本数据类型。

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

答案:
finally是一定会执行的 ,只有代码中有system.exit() 这一种情况 才不会执行finally ,因为终止了虚拟机进程 。

finally会在return之后执行。

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编译器会对它进行特殊处理,因此可以正确编译。

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

答案:
可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。

String s = new String("xyz");创建了几个String Object? 二者之间有什么区别?

答案:
两个或一个。 ”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。New String每写一遍,就创建一个新的对象,它依据那个常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’,这句代表就不会创建”xyz”自己了,直接从缓冲区拿。

abstract class和interface有什么区别?

答案:
含有abstract修饰符的class即为抽象类,abstract 类不能创建的实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体的子类中实现,所以不能有抽象构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。

接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。

两者的语法区别:

1.抽象类可以有构造方法,接口中不能有构造方法。

2.抽象类中可以有普通成员变量,接口中没有普通成员变量

3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。

  1. 抽象类中的抽象方法的访问类型可以是public,protected,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

  2. 抽象类中可以包含静态方法,接口中不能包含静态方法

  3. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。

  4. 一个类可以实现多个接口,但只能继承一个抽象类。

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

答案:
数组没有length()这个方法,有length的属性。

String有length()这个方法。

请说出作用域public,private,protected,以及不写时的区别

答案:
这四个作用域的可见范围如下表所示。

说明:如果在修饰的元素上面没有写任何访问修饰符,则表示friendly。

作用域当前类同一package子孙类其他package
public
protected×
friendly××
private×××

**备注:**只要记住了有4种访问权限,4个访问范围,然后将全选和范围在水平和垂直方向上分别按排从小到大或从大到小的顺序排列,就很容易画出上面的图了。

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

答案:
接口可以继承接口。

抽象类可以实现(implements)接口,抽象类可以继承实体类,但前提是实体类必须有明确的构造函数。抽象类中可以有静态的main方法。

java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?

答案:

  1. 有两种实现方法: 第一种 继承Thread类,重写run函数,调用start()开启线程。 第二种 实现Runnable接口,重写run函数,调用start()方法。

实现Runnable接口相对于继承Thread类来说,有如下显著的好处:

(1)适合多个相同程序代码的线程去处理同一资源的情况。

(2)可以避免由于Java的单继承特性带来的局限。

(3)有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。

  1. 用synchronized关键字修饰同步方法。

  2. 反对使用stop(),是因为它不安全;suspend()方法容易发生死锁。

Java有没有goto?

答案:
java中的保留字,现在没有在java中使用。

Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

答案:
Math.round(11.5)的结果为12;Math.round(-11.5)的结果为-11。

Math类中提供了三个与取整有关的方法:ceil、floor、round,这些方法的作用与它们的英文名称的含义相对应,

例如,ceil的英文意义是天花板,该方法就表示向上取整,Math.ceil(11.3)的结果为12,Math.ceil(-11.3)的结果是-11;

floor的英文意义是地板,该方法就表示向下取整,Math.floor(11.6)的结果为11,Math.floor(-11.6)的结果是-12;

最难掌握的是round方法,它表示“四舍五入”,算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整,

所以,Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。

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

答案:
在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。

在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。

静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。

什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用。

答案:
序列化:是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。

序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。

你所知道的集合类都有哪些?主要方法?

答案:
最常用的集合类是 List、Set 和 Map。

List 的具体实现包括 ArrayList 和 Vector,它们是可变大小的列表,比较适合构建、存储和操作任何类型对象的元素列表。主要方法:add,get,remove,contains。

Set 的具体实现包括 HashSet和TreeSet,集合元素是无效的且不可以重复。主要方法:add,get,remove,contains。

Map 提供了一个更通用的元素存储方法。 Map 集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值。主要方法:put,get,remove。

什么时候用assert?

答案:
assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。

在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,assert将给出警告或退出。

一般来说,assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能,在软件发布后,assertion检查通常是关闭的。

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

答案:
switch语句中的表达式只能是byte,short,char ,int以及枚举(enum),

所以当表达式是byte的时候可以隐含转换为int类型,而long字节比int字节多,不能隐式转化为int类型,所以switch语句可以用在byte上而不可以用在long上,

另外由于在JDK7.0中引入了新特性,所以switch语句可以接收一个String类型的值,String可以作用在switch语句上。

在JAVA中如何跳出当前的多重嵌套循环?

答案:
1、break在循环体内,强行结束循环的执行,也就是结束整个循环过程,不在判断执行循环的条件是否成立,直接转向循环语句下面的语句。

2、continue是跳出本次循环,继续执行下一次循环。

代码中的错误
1.
abstract class Name {
  private String name;
  public abstract boolean isStupidName(String name) {}
}

2.
public class Something {
  void doSomething () {
  private String s = ""; int l = s.length();
  }
}

3.
abstract class Something {
  private abstract String doSomething ();
}

4.
public class Something {
  public int addOne(final int x) {
    return ++x;
  }
}

答案:
1:错。abstract method必须以分号结尾,且不带花括号。

2:错。局部变量前不能放置任何访问修饰符 (private,public,和protected)。final可以用来修饰局部变量。

3:错。abstract的methods不能以private修饰。abstract的methods就是让子类implement(实现)具体细节的。

4:错。int x被修饰成final,意味着x不能在addOne method中被修改。

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

答案:
基本概念:线程,即轻量级进程,是程序执行流的最小单元。一个标准的线程由线程ID、当前指令指针(PC),寄存器集合和堆栈组成。线程是进程中的一个实体,是被系统独立调度和分派的基本单位。线程不拥有系统资源,近拥有少量运行必须的资源。

基本状态:就绪、阻塞和运行三种基本状态。

就绪状态,指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;

运行状态,指线程占有处理机正在运行;

阻塞状态,指线程在等待一个事件(如信号量),逻辑上不可执行。

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

答案:
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢。

Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差。

LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。 LinkedList也是线程不安全的,LinkedList提供了一些方法,使得LinkedList可以被当作堆栈和队列来使用。

HashMap和Hashtable的区别?

答案:
相同点:HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口。

不同点:1.HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。

2.Hashtable的方法是Synchronized的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。

说出一些常用的类,包,接口,请各举5个。

答案:
常用的类:BufferedReader,BufferedWriter,FileReader,FileWirter,String,Integer java.util.Date,System,Class,ArrayList,HashMap

常用的包:java.lang,java.io,java.util,java.sql,javax.servlet

常用的接口:List,Map,Servlet, HttpServletRequest, HttpServletResponse, Session, HttpSession

简述synchronized和java.util.concurrent.locks.Lock的异同?

答案:
主要相同点:Lock能完成synchronized所实现的所有功能 。

主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。Lock还有更强大的功能,例如,它的tryLock方法可以非阻塞方式去拿锁。

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

答案:
同步:如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。

异步:当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。

List、Map、Set三个接口,存取元素时,各有什么特点?

答案:
List特点:元素有放入顺序,元素可重复。 Set特点:元素无放入顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的)。 Map特点:元素按键值对存储,无放入顺序。

java中会存在内存泄漏吗,请简单描述。

答案:
会。

java导致内存泄露的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。

介绍Collection框架的结构

答案:
Collection:是单列集合,包含List列表和Set集 。

List 元素是有序的、可重复 ,可以对列表中每个元素的插入位置进行精确地控制; 可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素; 可存放重复元素,元素存取是有序的。

List接口中常用类

Vector: 线程安全,但速度慢,已被ArrayList替代。 底层数据结构是数组结构 。

lArrayList:线程不安全,查询速度快。 底层数据结构是数组结构 。

LinkedList:线程不安全。增删速度快。 底层数据结构是列表结构。

Set(集) 元素无序的、不可重复。 取出元素的方法只有迭代器。不可以存放重复元素,元素存取是无序的。

Set接口中常用的类

HashSet:线程不安全,存取速度快。 它是如何保证元素唯一性的呢?依赖的是元素的hashCode方法和euqals方法。

TreeSet:线程不安全,可以对Set集合中的元素进行排序。 它的排序是如何进行的呢?通过compareTo或者compare方法中的来保证元素的唯一性。元素是以二叉树的形式存放的。

Integer与int的区别

答案:
int是java提供的8种基本数据类型之一。

Java为每个基本类型提供了封装类,Integer是java为int提供的封装类。

int的默认值为0,而Integer的默认值为null,

即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。

描述一下JVM加载class文件的原理机制?

答案:
JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。

Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?

答案:
Set 里的元素是不能重复的。

元素重复与否是使用equals()方法进行判断的。

==判断引用值是否指向同一对象。

equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。

Collection 和 Collections的区别

答案:
Collection是集合类的上级接口,继承与它的接口主要有Set和List。

Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。

heap和stack有什么区别?

答案:
java的内存分为两类:一类是栈内存,一类是堆内存。

栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个栈中的变量也将随之释放。

堆是与栈作用不同的内存,一般用于存放不放在当前方法栈中的那些数据,例如,使用new创建的对象都放在堆里,所以它不会随方法的结束而消失。方法中的局部变量使用final修饰后,放在堆中,而不是栈中。

字节流与字符流的区别?

答案:
流的概念:Java中的流是对字节序列的抽象,我们可以想象有一个水管,只不过现在流动在水管中的不再是水,而是字节序列。和水流一样,Java中的流也具有一个“流动的方向”,通常可以从中读入一个字节序列的对象被称为输入流;能够向其写入一个字节序列的对象被称为输出流。

字节流:Java中的字节流处理的最基本单位为单个字节,它通常用来处理二进制数据。Java中最基本的两个字节流类是InputStream和OutputStream,它们分别代表了组基本的输入字节流和输出字节流。InputStream类与OutputStream类均为抽象类,我们在实际使用中通常使用Java类库中提供的它们的一系列子类。

字符流:Java中的字符流处理的最基本的单元是Unicode码元(大小2字节),它通常用来处理文本数据。所谓Unicode码元,也就是一个Unicode代码单元,范围是0x0000~0xFFFF。在以上范围内的每个数字都与一个字符相对应,Java中的String类型默认就把字符以Unicode规则编码而后存储在内存中。然而与存储在内存中不同,存储在磁盘上的数据通常有着各种各样的编码方式。使用不同的编码方式,相同的字符会有不同的二进制表示。

区别: 字节流操作的基本单元为字节;字符流操作的基本单元为Unicode码元。

字节流默认不使用缓冲区;字符流使用缓冲区。

字节流通常用于处理二进制数据,实际上它可以处理任意类型的数据,但它不支持直接写入或读取Unicode码元;字符流通常处理文本数据,它支持写入及读取Unicode码元。

两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?

答案:
对。

如果对象要保存在HashSet或HashMap中,它们的equals相等,那么,它们的hashcode值就必须相等。

如果不是要保存在HashSet或HashMap,则与hashcode没有什么关系了,这时候hashcode不等是可以的,例如arrayList存储的对象就不用实现hashcode,当然,我们没有理由不实现,通常都会去实现的。

说说&和&&的区别

答案:
&和&&都可以用作逻辑与的运算符,

&表示逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则,只要有一方为false,则结果为false。

&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式,

例如,对于if(str != null && !str.equals(“”))表达式,当str为null时,后面的表达式不会执行,所以不会出现NullPointerException。

如果将&&改为&,则会抛出NullPointerException异常。int x=33,If(x==33 & ++y>0) y会增长,If(x==33 && ++y>0)不会增长 。

&还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位,例如,0x31 & 0x0f的结果为0x01。

List 和 Map 区别?

答案:
List: 是存储单列数据的集合,存储的数据是有顺序,并且允许重复。

Map:是存储键和值这样的双列数据的集合,存储的数据是没有顺序的,其键是不能重复的,它的值是可以有重复的。

Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?

答案:
可以继承其他类也可以实现其他接口。

ArrayList和Vector的区别

答案:
相同点:这两个类都实现了List接口,他们都是有序集合即存储在这两个集合中的元素的位置都是有顺序的,相当于一种动态的数组,我们以后可以按位置索引号取出某个元素,并且其中的数据是允许重复的。

不同点:
(1)同步性:Vector是线程安全的,也就是说它的方法之间是线程同步的,而ArrayList是线程序不安全的,它的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使用ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用Vector,因为不需要我们自己再去考虑和编写线程安全的代码。

(2)数据增长:ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加ArrayList与Vector的存储空间。Vector默认增长为原来两倍,而ArrayList的增长为原来的1.5倍。ArrayList与Vector都可以设置初始的空间大小,Vector还可以设置增长的空间大小,而ArrayList没有提供设置增长空间的方法。

sleep() 和 wait() 有什么区别?

答案:
sleep:是线程类(Thread)的方法,导致此线程暂停执行指定时间,将执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。

wait:是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常?

答案:
当前的add方法放入的是哪个对象,就调用哪个对象的compareTo方法,至于这个compareTo方法怎么做,就看当前这个对象的类中是如何编写这个方法的。

评论