JAVA面试700问(六)

原文地址 译者:olive(yhfolive@gmail.com)

1.wait(),notify()和notifyAll()的作用是什么?

  • wait():使当前线程停止,直到另一个线程调用notify()方法或notifyAll()方法.。
  • notify():唤醒这个对象的监视器上等待的一个线程。
  • notifyAll():将引发wait()状态的所有的线程变为就绪状态,所有的线程继续执行。这些线程将基于优先级以及基于JVM选择来执行。
  • 注意:这三个方法在被调用之前必须获得对象的锁。

2.File类与RandomAccessFile类之间的区别是什么?

基于操作系统的文件系统服务,比如文件、文件夹的创建,权限的核实,改变文件名等,都由java.io.File类提供。java.io.RandomAccessFile类提供对文件的随机访问。使用这个类同样可以读、写,操作数据,同时更为方便的是,这个类可以读写基本类型,这有助于以结构化的方式处理数据文件。

3.什么是同步方法和同步代码块?

同步方法用于控制在多线程下对对象的访问。获得对象的锁后,线程才能执行同步方法。
同步代码块是类似于同步方法。不同之处在于同步方法是类的一部分,并明确地被另外一个方法调用。而一个同步代码块是由其被包含的方法执行,而这个包含同步代码块的方法还要被另外一个方法调用。

4.什么是Java类加载器?什么又是动态类加载?

类可以被JVM访问并通过名称来引用。JVM启动后,这些类被JVM读取。

所有的类加载器以一定的层次关系被JVM识别。第一个被加载的类是所谓的“初始化类”,也就是包含main方法的类。这个类是由JVM本身加载。所有其他后续类,按照它们在 ‘class chaining’中出现的顺序被加载。每一个类加载器都会创建一个命名空间来唯一识别它们。每个JVM至少包含一个引导类加载器。

5.抽象类和接口之间的区别是什么?什么时候使用抽象类?什么时候使用接口?

一个抽象类除了具体方法外还有一个或多个抽象方法。所有抽象方法必须被它的子类覆盖。一个抽象类可以没有抽象方法。而接口只包含方法签名。

默认情况下,一个接口中的的所有方法都是public的和abstract的。需要的时候应该为接口中的方法提供访问说明符。接口的实现类必须提供所有接口中声明的方法的实现。

抽象类的声明以关键字abstract开始,接口以interface开始。
一个接口可以继承任意数量的接口,一个抽象类只能继承一个抽象类。
接口的成员变量都是public static 的,抽象类的成员变量可以有任意声明。

当一个类继承自另一个类后,它还可以实现多个接口。当一个类需要实现接口所有的方法时,接口就很有用。
覆盖抽象类的具体方法不是强制要求的。当值需要实现若干方法,并想利用继承的优势的时候,就可以使用抽象类

6.ArrayList和Vector的主要区别?HashMap和HashTable的主要区别?

ArrayList和Vector的区别:
Vector是同步的,ArrayList不是。
Vector默认大小为10,ArrayList没有默认大小。
Vector有一个方法,可以指定Vector的大小,ArrayList不行。
Vector扩容的时候成倍增长,而ArrayList以50%增长。

HashMap和Hashtable的区别:
Hashtable是同步的,Hashmap不是。
Hashtable的值不能为空,Hashmap可以。
HashMap不能保证map中元素的顺序不变。
HashMap通过Map接口来实现。哈希表通过继承Dictionary 类实现。

7.解释Java集合框架?Java集合框架带来什么好处?

集合是由一组对象组成的一个对象。集合框架,让应用程序更有效率,更少的硬编码,不同的对象由类似的实现。使用集合框架,主要是为了集合框架的标准性和简单性。

集合框架的又一个好处是,一组对象,没有顺序或类型类型也可以通过一个单一的对象来表示。
Java集合框架提供了以下好处:
•减少编程工作量
•提高程序的速度和质量
•允许无关的API之间协同工作
•减少学习和使用的成本
•不要去设计新的API
•促进软件重用

8.对象的浅克隆和深克隆的主要区别?

Shallow cloning and deep cloning in Java – April 02, 2009 at 17:00 PM by Vidya Sagar

浅克隆只克隆了对象的引用。
深克隆克隆对象本身。
两者的区别用Java实例不好理解,但如果用数据库来想会更好理解:
如果实体需要“级联删除”被删除那就就要深克隆。如果“级联删除”是没有必要删除就需要浅克隆。

Shallow cloning and deep cloning in Java – July 31, 2009 at 14:00 PM by Amit Satpute

当对象被浅复制的时候,结果是复制的结果和原来的引用指向相同的对象。由于这个原因,原来的引用对对象的改变会映射到复制的结果。
当对象被深克隆时,对象的值也被复制,由于两个对象维持独立的引用,对对象的改变不会相互影响。

9.final,finally finalize()的区别?

Final, finally and finalize() in Java – April 02, 2009 at 17:00 PM by Vidya Sagar

• final

final成员变量的值不能被改变。
final方法不能被重写。
final类不能被继承。

• finally

这是一个语句块,咱try /catch块后这个语句块一定会被执行。

• finalize()

当对象要被GC回收时,这个方法会执行。

Final, finally and finalize() in Java – April 02, 2009 at 17:00 PM by Vidya Sagar
• final – 一个关键字/访问修饰符用于定义常量。

• finally – 除了try块调用了System.exit(0), finally块总是与try和catch块一起。这是确保在发生error/exception的情况下,finally块都能执行。finally不仅用于异常处理,还可以用于清理代码,比如返回值,continue或break语句的使用,I/O流的关闭等,在finally块中执行清理代码是一种良好的编程习惯。

• finalize()  -此方法与垃圾回收相关。在系统清理资源之前,这个方法会被调用。

10.什么是类型转换?什么是向上转型和向下转型?什么情况下会抛出ClassCastException异常?

Type casting and down casting in Java – April 02, 2009 at 17:00 PM by Vidya Sagar

“类型转换”:把对象从一种类型转换为另一种类型的表达式。
向上转型是把子类转换成父类,例如把子类的引用赋予父类的引用。
向下转型是把父类转换为子类,例如把父类的引用赋予子类的引用。
无效的类型转换会抛出ClassCastException。它表示该应用程序试图将对象转换为子类,但这个子类而不是对象的实例。当试图向容器中插入不兼容的对象时也会抛出这个异常。

Type casting and down casting in Java – July 31, 2009 at 14:00 PM by Amit Satpute

将类型的值从一种类型到另一种类型叫做类型转换。
如:

[code lang=”java”]
int i =10;
float x = (float) i;
[/code]

向上和向下转型和类有关。
如:

Parent p = new Child();

11.有几种内部类,分别是什么?

Different types of inner classes in Java – April 02, 2009 at 17:00 PM by Vidya Sagar

有4种类型的内部类 – 成员内部类,局部内部类,静态内部类和匿名内部类。
1.成员内部类-类(外部类)的成员。
2.局部内部类-这是一个块中定义的内部类。
3.静态内部类-类似于静态成员,这个类本身是静态的。
4.匿名内部类-类没有名称,只能实现一个接口或继承自一个抽象类。

外部类不能任意访问内部类的成员。要做到这一点,外部类必须创建其内部类的对象(静态内部类除外)。内部类可以访问所有的外部类的成员,因为内部类就像是一个类的成员。
匿名内部类是使用的场景如下:一个对象创建后, 调用单一的方法,调用完成后立即回收对象。多用于事件驱动编程。
嵌套类用于AWT,Swing和applet。动作事件发生后匿名内部类或被调用。

12.什么是Java包?

当项目的规模变大后,项目文件的管理变得非常繁琐。较小的项目可以将相关的文件存储在单个位置。
包可以有效地用来管理需要编写很多代码的问题。
不同功能的文件可以保存在不同的包中,有类似或相关功能的文件可以保存在同一包中。
例如:文件中的java.io包中的文件包含I / O相关的功能,而在java.net包中的文件包含与网络相关的功能。
包是类的集合,可以避免命名空间的冲突。
多个有相同名字的文件不能放在同一个包中。
一个类层次结构可以创建和保存在一个包中。

包也可以被看作是一个类的容器类。

13.什么是Java本地方法?

Native methods in Java – posted by Amit SatputeJava

应用程序可以调用C,C ++或汇编代码。这样做有时是为了性能,有时为了使用底层操作系统的系统服务或者操作系统的GUI API。具体步骤为:

* 编写和编译java代码
* 然后创建一个C头文件
* 创建Ç存根文件
* 编写C代码
* 创建共享代码库(或DLL)
* 运行应用程序
Native methods in Java – posted by Vidya Sagar

可以用java调用c或者c++的代码。这个过程是处于性能的考虑,或访问底层操作系统。JNI框架就是为了执行这样的程序而设计的。

14.什么是Java反射API?

Reflection API in Java – posted by Amit Satpute

用反射API可以在运行获取类或者对象的相关信息。反射类可以在运行时动态调用另一个类的方法。使用反射类你可以获得一个实例的字段,并且改变字段的内容。反思API包含的java.lang.Class类和java.lang.reflects中的类:Field, Method, Constructor, Array, 和Modifier.

Reflection API in Java – posted by Vidya Sagar

反射是一个用于检查在JVM中运行的应用程序的运行时行为的一个过程。反射API允许运行时创建一个不知道类名的类的实例。定制的处理类可以在没有编译的情况下嵌入系统。所有这些处理类都是继承基类“MassageProcessor’而得到的。

15.解释私有构造器的作用。

Java private constructor – August 11, 2008, 19:00 pm by Amit Satpute

私有构造函数不能被任何派生类访问也不能被其他任何类访问。所以,如果对象尚未初始化,你必须提供一个public 的方法来调用私有构造函数,或者如果它已经被初始化,你就用这个public方法返回对象的实例。
这种方法对不能被被实例化的对象很有用。

Java private constructor – Feb 27, 2009, 17:35 pm by Vidya Sagar

私有构造器可以阻止其包含类和子类的外部实例化。对象可以被创建,但创造是在内部完成。
私有构造可在下列情况下使用:
类只有static的字段以及方法
一个只有static final 字段的类
单例模式
工厂方法
类型安全的枚举类

16.什么是静态初始化块?

Static Initializers in Java – posted by Amit Satpute

静态初始化块可以被看做一个,没有名字,没有参数,没有返回值的成员。没有必要从类定义之外引用它。语法:

static
{
//CODE
}

静态初始化块中的代码是由JVM进行类加载时执行。
因为它是在类加载时自动执行,参数对它来说没有任何意义,所以静态初始化块没有一个参数列表。

Static Initializers in Java – posted by Vidya Sagar

静态初始化块是一个名为’static’的代码块。一个类可以包含一个或多个静态初始化块。静态初始化块中的代码会先于构造器中的代码执行,并且按照各静态初始化快在类中的顺序执行。当类被加载的时候,静态初始化中的代码会被执行。
例如:

class Test
{
static int stNumber;
int number;
Test()
{
number = 10;
}
static
{
stNumber=30;
}
…… // other methods here

}

在上面的例子中,静态初始化块中的代码先执行,然后用才是构造器中的代码。

17.&和&&的区别?

Java – Boolean & operator and the && operator – Feb 28, 2010 at 16:16 PM by Vidya Sagar

&&用于两个关系式的逻辑与运算
&用于两个数的按位与运算

18.什么是任务的优先级和它是如何被调度的?

Java – task’s priority – Feb 28, 2010 at 16:16 PM by Vidya Sagar

一个任务的优先级是一个整数值。这个值用于各个任务之间执行的相对顺序。调度是任务执行的顺序它被任务调度器控制。任务调度器会尝试让具有较高优先级的任务在优先级较低的任务之前执行。

Java – task’s priority – Jan 15, 2009 at 8:10 am by Amit Satpute
优先级是一个整数值。
任务调度器会根据这个值来确定何时执行这个任务。

19.抢占式调度和时间分片之间的区别是什么?

Java – Preemptive scheduling and time slicing – Feb 28, 2010 at 16:16 PM by Vidya Sagar

抢占式调度:具有最高优先级的任务将被执行,直到它进入等待或死亡状态。
时间分片:任务执行特定的和预先确定的时间片,然后重新进入就绪任务池。调度器的任务根据优先级以及其他因素来确定下一个要执行的任务。

Java – Preemptive scheduling and time slicing – Jan 15, 2009 at 8:10 am by Amit Satpute

如果某一个任务正在运行并且所使用的调度方法是抢占式调度,那么如果存在比正在执行的任务更高优先级的另一个任务,那么正在执行的任务将会被具有更高优先级的任务抢占。
在时间分片的调度方法中,任务会执行特定的时间片。
任务执行完后,如果存在具有更高优先级的另一项任务,调度器要执行的下一个任务取决于任务的优先级以及其他因素。

20.什么是同步的,为什么它很重要?

Java – synchronization – Feb 28, 2010 at 16:16 PM by Vidya Sagar

在多线程中访问共享资源时,只有一个线程可以在同一时间访问一个指定的资源,称为同步。
同步用于防止多线程造成的数据的不一致。
对于多线程,同步具有控制多个线程对共享资源访问的能力。在非同步时,可能有一个线程真在修改一个共享变量,同时另一个线程在更新相同的共享数据。

Java – synchronization – Jan 15, 2009 at 8:10 am by Amit Satpute

线程通过访问共享字段和对象实现通信。
然而,有线程冲突和内存不一致的可能性。
同步是用来防止这种情况。
在同步中,如果一个对象对多个线程是可见的,所有读取或写入该对象的变量,通过同步的方式进行。

21.如何使用Observer类和Observable接口?

Java – Observer and Observable – Jan 15, 2009 at 8:10 am by Amit Satpute

Observable 类代表一个可观察的对象。
要被观察的对象可以用Observable 类的子类来表示。
当Observable实例发生改变时 ,应用程序调用Observable对象的notifyObservers方法,通知它的所有Observer,这些Observer会调用它们的update()方法响应通知。

22.什么是ResultSetMetaData的?

Java – What is ResultSetMetaData? – Jan 15, 2009 at 8:10 am by Amit Satpute

ResultSetMetaData的是一个对象,用于获取ResultSet对象的类型和列的属性的信息。
如下:

ResultSet resultSet1 = statement1.executeQuery(“SELECT a, b, c FROM TABLE2”);
ResultSetMetaData rsmd = rs.getMetaData();

23.解释CacheRowset,JdbcRowSet的和的WebRowSet。

Java – CacheRowset, JDBCRowset and WebRowset – Jan 15, 2009 at 8:10 am by Amit Satpute

JdbcRowSet是一种保持连接的rowset ,它使用JDBC驱动保持和数据源的连接。
CachedRowSet和WebRoeSet是不保持连接的结果集,仅当它们读取或者写入数据的时候才和数据源连接。

如下几个例子:
Example 1:

JdbcRowSet j = new JdbcRowSetImpl();
j.setCommand(“SELECT * FROM TABLE_NAME);
j.setURL(“jdbc:myDriver:myAttribute”);
j.setUsername(“XXX”);
j.setPassword(“YYYo”);
j.execute();
Example 2:
ResultSet rs = stmt.executeQuery(“SELECT * FROM AUTHORS”);
CachedRowSet crset = new CachedRowSetImpl();
crset.populate(rs);
Example 3:
WebRowSet wrs = new WebRowSetImpl();
wrs.populate(rs);
wrs.absolute(2)
wrs.updateString(1, “stringXXX”);

24.解释一类的静态和非静态成员之间的差异。

Java – difference between Static and Non-Static fields – Feb 22, 2009 at 10:10 am by Vidya Sagar

静态成员属于类。该类的对象不能有这些字段的副本。这些字段由类来直接引用。例如:Employee. company。无需创建该类的一个实例,这些字段也可被访问。

非静态字段由类的所有对象访问。每个对象有非静态字段的一个副本。要使用非静态字段,必须先创建类的实例。

25.instanceof关键字的作用。

Java – Describe the use of “instanceof” keyword. – with answers posted on July 22, 2008 at 8:10 am

“instanceof” 用于检查一个对象是什么类型。

26.垃圾回收机制有什么缺点?

Java – What is the disadvantage of garbage collector? – with answers posted on July 22, 2008 at 8:10 am

尽管垃圾收集器在它自己的线程中运行,但仍然对性能有影响。它增加了开销,因为JVM必须跟踪所有未被引用的对象,然后释放这些未引用的对象。
垃圾收集器可使用“的System.gc”或“Runtime.gc”来强制执行。

27.资源清理(Finalization)的作用?

Java – What is the purpose of finalization? – July 06, 2009 at 10:00 AM

Finalization通过调用finalized()实现。Finalization的目的是为了对象得到清理之前执行某些操作。此方法在GC之前执行必要的清理工作,也就是消除’orphan objects’.

28.定义类和对象并使用Java的例子解释。

Java – Define class and object. – Feb 14, 2009 at 8:10 am by Vidya Sagar

类:类是一个封装了数据和在数据上的操作的程序结构。在面向对象的编程中,类可以看成对象的蓝图。
对象:一个对象是属于某个类的程序结构,具有状态和行为。
例如 Employee 是一个类
具有的唯一标识的一个Employee 是一个对象的一个​​例子。

class Employee
{
// instance variables declaration
// Methods definition
}

一个employee 对象是一个特定的employee

Employee vismay =new Employee();

vismay 是此对象的引用。

29.解释类和实例?

Java – Explain class vs. instance with example using java. – Feb 16, 2009 at 19:50 am by Vidya Sagar

一类是封装了数据和操作上的操作的程序结构。它是一个对象的蓝图。
一个对象可以被称为一个类的一个“实例”。
类中声明的变量和方法,除方法中的变量外都被称为实例变量,他们在每个对象中都有一份拷贝。一旦对象被创建,可以说,创建了一个类的实例。
类变量和方法创建一次,而每次创建一个对象都会创建实例变量和成员

30.什么是方法?说出几种方法的签名。

Java – What is a method? Provide several signatures of the methods – July 06, 2009 at 10:00 AM

java方法是一组执行任务的语句。一个方法要被放在类中。
方法签名:方法的名字,返回类型和参数的数目组成方法签名。

一个成员可以有以下方法签名:
访问说明符- public, private, protected 等
访问修饰符- static, synchronized等
返回类型- void, int, String 等
方法的名字-
参数

31.创建类实例的方法有几种?分别给出描述。

Java – Explain how to create instance of a class by giving an example. – Feb 18, 2009 at 9:10 am by Vidya Sagar

Java 有三种创建类实例的方法:

* 用 new 操作符

* 用 Class.forName(classname).newInstance() method

* 用 clone() 方法

32.什么是单例类?有什么用途?

Java – What is singleton class? Where is it used? – Feb 18, 2009 at 9:10 am by Vidya Sagar

一个类可以定义为单例类,当且仅当它只能创建一个类的实例。当应用中想只适用类的一个实例时单例类会很有用。
以下是一些单例类的用途。
1.对对象的访问进行控制。
2.当全局范围需要”just-in-time”实例化的时候。

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: JAVA面试700问(六)

  • Trackback 关闭
  • 评论 (4)
    • wyc3146
    • 2015/03/13 1:54下午

    二到五怎么找不到?

      • yhfolive
      • 2015/03/13 2:32下午

      不好意思哦,2和3的这几个类我都没有用过,翻译的时候以为是Android的几个类了。我去学习一下,试试能不能加进去。

    • 付政委
    • 2015/03/19 10:08上午

    6.ArrayList和Vector的主要区别?HashMap和HashTable的主要区别?

    ArrayList和Vector的区别:
    Vector是同步的,ArrayList不是。
    Vector默认大小为10,ArrayList没有默认大小。
    Vector有一个方法,可以指定Vector的大小,ArrayList不行。
    Vector扩容的时候成倍增长,而ArrayList以50%增长。
    ================================================ Why?
    ArrayList是经常会被用到的,一般情况下,使用的时候会像这样进行声明:
    List arrayList = new ArrayList();
    如果像上面这样使用默认的构造方法,初始容量被设置为10。当ArrayList中的元素超过10个以后,会重新分配内存空间,使数组的大小增长到16。
    可以通过调试看到动态增长的数量变化:10->16->25->38->58->88->…

    也可以使用下面的方式进行声明:
    List arrayList = new ArrayList(4);
    将ArrayList的默认容量设置为4。当ArrayList中的元素超过4个以后,会重新分配内存空间,使数组的大小增长到7。
    可以通过调试看到动态增长的数量变化:4->7->11->17->26->…

    那么容量变化的规则是什么呢?请看下面的公式:
    ((旧容量 * 3) / 2) + 1

      • yhfolive
      • 2015/03/19 6:46下午

      谢谢指正。答主可能没说清细节吧。 我去看了,其实不在意细节的话就是以 (当前list中的元素数目)/2 的大小扩容了。

      代码如下:

      //minCapacity =原来底层数组的长度+新加入元素的数目。
      private void ensureCapacityInternal( int minCapacity) {
      if (elementData == EMPTY_ELEMENTDATA) {
      //如果底层数组为空那么minCapacity为10与minCapacity的较大者
      minCapacity = Math.max( DEFAULT_CAPACITY , minCapacity );
      }

      ensureExplicitCapacity( minCapacity );
      }

      //modCount用于记录ArrayList在结构上被修改的操作次数,比如remove,add等,当ArrayList被迭代的时候如果modCount被修改,就会抛出ConcurrentModificationException

      private void ensureExplicitCapacity( int minCapacity) {
      modCount++;

      // overflow-conscious code
      if (minCapacity – elementData .length > 0)
      grow( minCapacity );
      }

      private void grow(int minCapacity ) {
      // overflow-conscious code
      int oldCapacity = elementData .length ;

      //newCapacity =oldCapacity+oldCapacity/2 增加原来大小的50%

      int newCapacity = oldCapacity + (oldCapacity >> 1);

      //元素数目教少的时候,newCapacity 取决于minCapacity ,如前面
      if (newCapacity – minCapacity 0)
      //下面这个方法,如果 minCapacity > MAX_ARRAY_SIZE) 则返回Integer. MAX_VALUE,否则返回MAX_ARRAY_SIZE
      newCapacity = hugeCapacity( minCapacity );
      // minCapacity is usually close to size, so this is a win:
      elementData = Arrays.copyOf( elementData , newCapacity );
      }

      总结:当list中元素数目在0-10之间时,每次执行add底层数组大小不变。当底层数组元素数目大于10后,如果底层数组有足够空间则不扩容,如果底层数组空间不够则扩容 (当前底层数组长度)/2。至于new ArrayList(4)的方式,在初始化时底层数组不为空,结果是当需要扩容时,扩容 (当前底层数组长度)/2。

return top