关于Java 部分的160道面试题(二)

51、abstract class(抽象类)和 interface(接口)有什么区别? 【百度应用中心面试
题】
【参考答案】
含有 abstract 修饰符的 class 即为抽象类,abstract 类不能创建的实例对象。含有
abstract 方法的类必须定义为 abstract class,abstract class 类中的方法不必是抽象的。
abstract class 类中定义抽象方法必须在具体(Concrete)子类中实现,所以,不能有抽象
构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必
须定义为 abstract 类型。
接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。
接口中的方法定义默认为 public abstract 类型,接口中的成员变量类型默认为 public
static final。
下面比较一下两者的语法区别:
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非
抽象的普通方法。
4. 抽象类中的抽象方法的访问类型可以是 public,protected 和(默认类型,虽然
eclipse 下不报错,但应该也不行),但接口中的抽象方法只能是 public 类型的,并且
默认即为 public abstract 类型。
5. 抽象类中可以包含静态方法,接口中不能包含静态方法
6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可
以任意,但接口中定义的变量只能是 public static final 类型,并且默认即为 public
static final 类型。
7. 一个类可以实现多个接口,但只能继承一个抽象类。
下面接着再说说两者在应用上的区别:
【分析】
这道题的思路是先从总体解释抽象类和接口的基本概念,然后再比较两者的语法细节,
最后再说两者的应用区别。比较两者语法细节区别的条理是:先从一个类中的构造方法、普
通成员变量和方法(包括抽象方法),静态变量和方法,继承性等方面来回答。
52、Collection 框架中实现比较要实现什么接口?
【参考答案】
Comparable、Comparator 接口
53、是否可以继承 String 类?
【参考答案】
String 类是 final 类故不可以继承。
54、String 和 StringBuffer 的区别
【参考答案】
JAVA 平台提供了两个类:String 和 StringBuffer,它们可以储存和操作字符串,即包含
多个字符的字符数据。String 类表示内容不可改变的字符串。而 StringBuffer 类表示内容可
以被修改的字符串。当你知道字符数据要改变的时候你就可以使用 StringBuffer。典型地,
你可以使用 StringBuffers 来动态构造字符数据。另外,String 实现了 equals 方法,new
String(“abc”).equals(new String(“abc”)的结果为 true,而 StringBuffer 没有实现 equals
方法,所以,new StringBuffer(“abc”).equals(new StringBuffer(“abc”)的结果为 false。
String 覆盖了 equals 方法和 hashCode 方法,而 StringBuffer 没有覆盖 equals 方法和
hashCode 方法,所以,将 StringBuffer 对象存储进 Java 集合类中时会出现问题。
55、StringBuffer 与 StringBuilder 的区别
【参考答案】
StringBuffer 和 StringBuilder 类都表示内容可以被修改的字符串,StringBuilder
是线程不安全的,运行效率高,如果一个字符串变量是在方法里面定义,这种情况只可能有
一个线程访问它,不存在不安全的因素了,则用 StringBuilder。如果要在类里面定义成员
变量,并且这个类的实例对象会在多线程环境下使用,那么最好用 StringBuffer。
56、try {}里有一个 return 语句,那么紧跟在这个 try 后的 finally {}里的 code 会不会
被执行,什么时候被执行,在 return 前还是后? 【杭州天眼科技】
【参考答案】
答案是在 return 之前。
【分析】
程序代码的运行结果:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(new Test().test());;
}
static int test()
{
int x = 1;
try
{
return x;
}
finally
{
++x;
}
}
}
---------执行结果 ---------
1
运行结果是 1,为什么呢?主函数调用子函数并得到结果的过程,好比主函数准备一个
空罐子,当子函数要返回结果时,先把结果放在罐子里,然后再将程序逻辑返回到主函数。
所谓返回,就是子函数说,我不运行了,你主函数继续运行吧,这没什么结果可言,结果是
在说这话之前放进罐子里的。
下面的程序代码输出的结果是多少?
public class smallT
{
public static void main(String args[])
{
smallT t = new smallT();
int b = t.get();
System.out.println(b);
}
public int get()
{
try
{
return 1 ;
}
finally
{
return 2 ;
}
}
}
返回的结果是 2。
我可以通过下面一个例子程序来帮助我解释这个答案,从下面例子的运行结果中可以发现,
try 中的 return 语句调用的函数先于 finally 中调用的函数执行,也就是说 return 语句先
执行,finally 语句后执行,所以,返回的结果是 2。Return 并不是让函数马上返回,而是
return 语句执行后,将把返回结果放置进函数栈中,此时函数并不是马上返回,它要执行
finally 语句后才真正开始返回。
在讲解答案时可以用下面的程序来帮助分析:
public class Test {
/**

  • @param args add by zxx ,Dec 9, 2008
    /
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    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 和 break 语句后执行。
    57、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 异常。
    58、多线程有几种实现方法?同步有几种实现方法?
    【参考答案】
    多线程有两种实现方法,分别是继承 Thread 类与实现 Runnable 接口。
    同步的实现方面有两种,分别是 synchronized,wait 与 notify 。
    a. wait():使一个线程处于等待状态,并且释放所持有的对象的 lock。
    b. sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉
    InterruptedException 异常。
    c. notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确
    切的唤醒某一个等待状态的线程,而是由 JVM 确定唤醒哪个线程,而且不是按优
    先级。
    d. allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的
    锁,而是让它们竞争。
    59、启动一个线程是用 run()还是 start()?
    【参考答案】
    启动一个线程是调用 start()方法,使线程就绪状态,以后可以被调度为运行状态,一
    个线程必须关联一些具体的执行代码,run()方法是该线程所关联的执行代码。
    60、内部类可以引用外部类的成员吗?有没有什么限制?
    【参考答案】
    完全可以。如果不是静态内部类,那没有什么限制!
    如果你把静态嵌套类当作内部类的一种特例,那在这种情况下不可以访问外部类的普通
    成员变量,而只能访问外部类中的静态成员。
    61、List 和 Map 区别?【软通动力】
    【参考答案】
    一个是存储单列数据的集合,另一个是存储键和值这样的双列数据的集合,List 中存
    储的数据是有顺序,并且允许重复;Map 中存储的数据是没有顺序的,其键是不能重复的,
    它的值是可以有重复的。
    62、ArrayList 和 Vector 的区别【博炎科技】
    【参考答案】
    这两个类都实现了 List 接口(List 接口继承了 Collection 接口),他们都是有序集合,
    即存储在这两个集合中的元素的位置都是有顺序的,相当于一种动态的数组,我们以后可以
    按位置索引号取出某个元素,并且其中的数据是允许重复的。
    接着说 ArrayList 与 Vector 的区别,这主要包括两个方面:
    1、同步性:
    Vector 是线程安全的,也就是说是它的方法之间是线程同步的,而 ArrayList 是线程
    序不安全的,它的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使
    用 ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最
    好是使用 Vector,因为不需要我们自己再去考虑和编写线程安全的代码。
    备注:对于 Vector&ArrayList、Hashtable&HashMap,要记住线程安全的问题,记住
    Vector 与 Hashtable 是旧的,是 java 一诞生就提供了的,它们是线程安全的,ArrayList
    与 HashMap 是 java2 时才提供的,它们是线程不安全的。
    2、数据增长:
    ArrayList 与 Vector 都有一个初始的容量大小,当存储进它们里面的元素的个数超过
    了容量时,就需要增加 ArrayList 与 Vector 的存储空间,每次要增加存储空间时,不是只
    增加一个存储单元,而是增加多个存储单元,每次增加的存储单元的个数在内存空间利用与
    程序效率之间要取得一定的平衡。Vector 默认增长为原来两倍,而 ArrayList 的增长为原
    来的 1.5 倍。ArrayList 与 Vector 都可以设置初始的空间大小,Vector 还可以设置增长的
    空间大小,而 ArrayList 没有提供设置增长空间的方法。
    63、heap 和 stack 有什么区别。
    【参考答案】
    Java 的内存分为两类,一类是栈内存,一类是堆内存。栈内存是指程序进入一个方法
    时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个
    方法结束时,分配给这个方法的栈会释放,这个栈中的变量也将随之释放。
    堆是与栈作用不同的内存,一般用于存放不放在当前方法栈中的那些数据,例如,使用
    new 创建的对象都放在堆里,所以,它不会随方法的结束而消失。方法中的局部变量使
    用 final 修饰后,放在堆中,而不是栈中。
    64、Java 类实现序列化的方法(二种)?如在 collection 框架中实现排序,要实现什么
    样的接口
    【参考答案】
    java.io.Serializable 接口或实现 Externalizable 接口。
    Collection 框架中实现比较要实现 Comparable 接口或 Comparator 接口,并实现比较方

    65、JAVA 实现向数据库添加一列。
    【参考答案】
    Connection con = null;
    ResultSet rs = null;
    Class.forName(“com.microsoft.jdbc.sqlserver.SQLServerDriver”);
    String url=“jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=db_name”;
    Connection con = DriverManager.getConnection(url,"","");
    StateManager sm =con.createStateMent();
    String sql = " alter table student add age int; “;
    rs = sm.excute(sql);
    66、什么是 Java 序列化,如何实现 java 序列化?或者请解释 Serializable 接口的作用。
    【东软国际】
    【参考答案】
    序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可
    以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决
    在对对象流进行读写操作时所引发的问题。
    序列化的实现:将需要被序列化的类实现 Serializable 接口,该接口没有需要实现的
    方法,implements Serializable 只是为了标注该对象是可被序列化的,然后使用一个输出
    流 ( 如 : FileOutputStream) 来 构 造 一 个 ObjectOutputStream( 对 象 流 ) 对 象 , 使 用
    ObjectOutputStream 对象的 writeObject(Object obj)方法就可以将参数为 obj 的对象写出, 那么在另一端,通过 ObjectInputStream 对象的 readObject(Object obj)获取到字节流数
    据后,要将字节流转换成原对象,这叫反序列化,以便将数据存储在文件中或在网络传输。
    Serializable 接口描述启用其序列化功能,未实现此接口的类将无法使其任何状态序列
    化或反序列化。Serializable 接口没有方法或字段,仅用于标识可序列化的语义,标识实现
    了该接口的对象属性可被序列化。
    67、Java 中有几种类型的流?JDK 为每种类型的流提供了一些抽象类以供继承,请说出他
    们分别是哪些类?
    【参考答案】
    字节流,字符流两种类型流。字节流继承于 InputStream、 OutputStream;字符流继
    承于 Reader、Writer。 其它与 IO 操作相关的类都是派生至上述 4 个抽象类,如字节相关
    的:FileInputStream、FileOutputStream 类;字符相关的:BufferedReader、BufferedWriter

    68、用 JDBC 如何调用存储过程
    【参考答案】
    通过JDBC组件中的CallableStatement接口实现调用存储过程。
    核心代码如下:
    Class.forName(“com.mysql.jdbc.Driver”);
    Connection conn=
    DriverManager.getConnection(“jdbc:mysql:///test”,“root”,“root”);
    CallableStatement cstmt = cn.prepareCall(”{call
    insert_Student(?,?,?)}");
    cstmt.registerOutParameter(3,Types.INTEGER);
    cstmt.setString(1, “wangwu”);
    cstmt.setInt(2, 25);
    cstmt.execute();
    69、JAVA 事件有哪些模式?
    【参考答案】
    1、事件直接驱动模式。它的特点是直接而且快,是必须经常使用的,主要适合于迅速
    处理 前台的命令,通常就是我们说的 command(命令)模式。。2.监控式事件模式。主要借
    助第三者来监控和触发事件,就是通常我们说的观察者模式。特点是: 有一个观察者置身
    事外在定期独立运行着,我们将我们要监听的事件向这个观察者注册,这样观察者就 代替
    我们来监听这个事件,应用客户端通过观察者来获得事件状况。
    【分析】
    70、JVM 加载 class 文件原理?
    【参考答案】
    所谓装载就是寻找一个类或是一个接口的二进制形式并用该二进制形式来构造代表这
    个类或是这个接口的 class 对象的过程. 在 Java 中,类装载器把一个类装入 Java 虚拟机中,要经过三个步骤来完成:装载、链
    接和初始化,其中链接又可以分成校验、准备、解析
    装载:查找和导入类或接口的二进制数据;
    链接:执行下面的校验、准备和解析步骤,其中解析步骤是可以选择的;
    校验:检查导入类或接口的二进制数据的正确性;
    准备:给类的静态变量分配并初始化存储空间;
    解析:将符号引用转成直接引用;
    初始化:激活类的静态变量的初始化 Java 代码和静态 Java 代码块
    JVM 中类的装载是由 ClassLoader 和它的子类来实现的,Java ClassLoader 是一个重要的
    Java 运行时系统组件。它负责在运行时查找和装入类文件的类
    一个 Java 应用程序使用两种类型的类装载器:根装载器(bootstrap)和用户定义的装载器
    (user-defined)。
    根装载器以某种默认的方式将类装入,包括那些 Java API 的类。在运行期间一个 Java 程
    序能安装用户自己定义的类装载器。根装载器是虚拟机固有的一部分,而用户定义的类装载
    器则不是,它是用 Java 语言写的,被编译成 class 文件之后然后再被装入到虚拟机,并像
    其它的任何对象一样可以被实例化。 Java 类装载器的体系结构如下所示:
    Bootstrap(根装载器)
    |
    Extension (扩展装载器)
    |
    System
    |
    UserDefine1
    /
    UserDefine2 UserDefine3
    |
    UserDefine4
    Java 的类装载模型是一种代理(delegation)模型。当 JVM 要求类装载器 CL(ClassLoader)
    装载一个类时,CL 首先将这个类装载请求转发给他的父装载器。只有当父装载器没有装载并
    无法装载这个类时,CL 才获得装载这个类的机会。这样, 所有类装载器的代理关系构成了
    一种树状的关系。树的根是类的根装载器(bootstrap ClassLoader) , 在 JVM 中它以
    "null"表示。除根装载器以外的类装载器有且仅有一个父装载器。在创建一个装载器时, 如
    果没有显式地给出父装载器, 那么 JVM 将默认系统装载器为其父装载器
    下面针对各种类装载器分别进行详细的说明:
    根(Bootstrap) 装载器:该装载器没有父装载器,它是 JVM 实现的一部分,从
    sun.boot.class.path 装载运行时库的核心代码。
    扩展(Extension) 装载器:继承的父装载器为根装载器,不像根装载器可能与运行时的
    操作系统有关,这个类装载器是用纯 Java 代码实现的,它从 java.ext.dirs (扩展目录)
    中装载代码。
    系统(System or Application) 装载器:装载器为扩展装载器,我们都知道在安装
    JDK 的 时 候 要 设 置 环 境 变 量 (CLASSPATH ) , 这 个 类 装 载 器 就 是 从
    java.class.path(CLASSPATH 环境变量)中装载代码的,它也是用纯 Java 代码实现的,同
    时还是用户自定义类装载器的缺省父装载器。
    小应用程序(Applet) 装载器: 装载器为系统装载器,它从用户指定的网络上的特定目
    录装载小应用程序代码。
    71、SOCKET 中有几中连接方式,各有什么区别?
    【参考答案】
    Sockets 有两种主要的操作方式:面向连接(TCP/IP)的和无连接(UDP)的。无连接的操作
    使用数据报协议,无连接的操作是快速的和高效的,但是数据安全性不佳. 面向连接的操作
    使用 TCP 协议.面向连接的操作比无连接的操作效率更低,但是数据的安全性更高
    【分析】
    72、抽象类能否被实例化 ?抽象类的作用是什么?
    【参考答案】
    抽象类一般不能被实例化;抽象类通常不是由程序员定义的,而是由项目经理或模块设
    计人 设计抽象类的原因通常是为了规范方法名 抽象类必须要继承,不然没法用,作为模块
    设计者,可以把让底层程序员直接用得方法直接调用,而一些需要让程序员覆盖后自己做得
    方法则定义称抽象方法
    【分析】
    73、Linkedlist、Arraylist 内部是如何实现的(更深入的问了 LinkedList 与 ArrayList
    的区别) 【天威诚信面试题】
    【参考答案】
    ArrayList 的内部实现是基于内部数组 Object[],它更像是对数组实现的一种封装,所
    以在向 ArrayList 的前面或中间插入数据时,必须将其后的所有数据相应的后移,这样必然
    要花费较多时间。
    而 LinkedList 的内部实现是基于一组双向链表实现的存储特性,所以提供了链表一样
    访问的 API 接口,它们在性能上有很大的差别。当你访问 Linkedlist 链表中的某个元素时,
    就必须从链表的一端开始沿着连接方向一个一个元素地去查找,直到找到所需的元素为止,
    所以,当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元
    素时,就应该使用 LinkedList 了。
    而当你的操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问
    其中的元素时,使用 ArrayList 会提供比较好的性能。
    【分析】
    74、Hashtable 的原理【北辰网络】
    【参考答案】
    通过节点的关键码确定节点的存储位置,即给定节点的关键码 k,通过一定的函数关系 H(散
    列函数),得到函数值 H(k),将此值解释为该节点的存储地址
    75、JDBC 中的 PreparedStatement 相比 Statement 的好处?
    【参考答案】
    预编译语句 java.sql.PreparedStatement ,扩展自 Statement,不但具有 Statement
    的所有能力而且具有更强大的功能。不同的是,PreparedStatement 是在创建语句对象的同
    时给出要执行的 sql 语句。这样,sql 语句就会被系统进行预编译,执行的速度会有所增加,
    尤其是在执行大语句的时候,效果更加理想
    76、sleep()和 wait()区别
    【参考答案】
    sleep() 方法:线程主动放弃 CPU,使得线程在指定的时间内进入阻塞状态,不能得到
    CPU 时间,指定的时间一过,线程重新进入可执行状态。典型地,sleep() 被用在
    等待某个资源就绪的情形:测试发现条件不满足后,让线程阻塞一段时间后重新测
    试,直到条件满足为止。
    wait( ) :与 notify()配套使用,wait()使得线程进入阻塞状态,它有两种形式,一
    种允许指定以毫秒为单位的一段时间作为参数,另一种没有参数,当指定时间参数时
    对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态,后者则必须
    对应的 notify() 被调用
    (网上的答案:sleep 是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行
    机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用 sleep 不会释放对象锁。
    wait 是 Object 类的方法,对此对象调用 wait 方法导致本线程放弃对象锁,进入等待此对
    象的等待锁定池,只有针对此对象发出 notify 方法(或 notifyAll)后本线程才进入对象
    锁定池准备获得对象锁进入运行状态。)
    sleep 就是正在执行的线程主动让出 cpu,cpu 去执行其他线程,在 sleep 指定的时间
    过后,cpu 才会回到这个线程上继续往下执行,如果当前线程进入了同步锁,sleep 方法并
    不会释放锁,即使当前线程使用 sleep 方法让出了 cpu,但其他被同步锁挡住了的线程也无
    法得到执行。wait 是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便
    其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了 notify 方法(notify
    并不释放锁,只是告诉调用过 wait 方法的线程可以去参与获得锁的竞争了,但不是马上得
    到锁,因为锁还在别人手里,别人还没释放。如果 notify 方法后面的代码还有很多,需要
    这些代码执行完后才会释放锁,可以在 notfiy 方法后增加一个等待和一些代码,看看效果),
    调用 wait 方法的线程就会解除 wait 状态和程序可以再次得到锁后继续向下运行。对于 wait
    的讲解一定要配合例子代码来说明,才显得自己真明白。
    package com.huawei.interview;
    public class MultiThread {
    /
    *
  • @param args
    /
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    new Thread(new Thread1()).start();
    try {
    Thread.sleep(10);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    new Thread(new Thread2()).start();
    }
    private static class Thread1 implements Runnable
    {
    @Override
    public void run() {
    // TODO Auto-generated method stub
    //由于这里的Thread1和下面的Thread2内部run方法要用同一对象作为监视器,我们这里不
    能用this,因为在Thread2里面的this和这个Thread1的this不是同一个对象。我们用
    MultiThread.class这个字节码对象,当前虚拟机里引用这个变量时,指向的都是同一个对
    象。
    synchronized (MultiThread.class) {
    System.out.println(“enter thread1…”);
    System.out.println(“thread1 is waiting”);
    try {
    //释放锁有两种方式,第一种方式是程序自然离开监视器的范围,也就是离开了
    synchronized关键字管辖的代码范围,另一种方式就是在synchronized关键字管辖的代码内
    部调用监视器对象的wait方法。这里,使用wait方法释放锁。
    MultiThread.class.wait();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    System.out.println(“thread1 is going on…”);
    System.out.println(“thread1 is being over!”);
    }
    }
    }
    private static class Thread2 implements Runnable
    {
    @Override
    public void run() {
    // TODO Auto-generated method stub
    synchronized (MultiThread.class) {
    System.out.println(“enter thread2…”);
    System.out.println(“thread2 notify other thread can release wait
    status…”);
    //由于notify方法并不释放锁, 即使thread2调用下面的sleep方法休息了10毫秒,但
    thread1仍然不会执行,因为thread2没有释放锁,所以Thread1无法得不到锁。
    MultiThread.class.notify();
    System.out.println(“thread2 is sleeping ten millisecond…”);
    try {
    Thread.sleep(10);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    System.out.println(“thread2 is going on…”);
    System.out.println(“thread2 is being over!”);
    }
    }
    }
    })
    77、概述反射和序列化
    【参考答案】
    Reflection:是 Java 被视为动态语言的一个关键性质。这个机制允许程序在运行时透过
    Reflection APIs 取得任何一个已知名称的 class 的内部信息,包括其 modifiers(诸如
    public, static 等等)、superclass(例如 Object)、实现之 interfaces(例如 Cloneable),
    也包括 fields 和 methods 的所有信息,并可于运行时改变 fields 内容或唤起 methods。
    序列化:就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。
    可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解
    决在对对象流进行读写操作时的问题。
    78、Java 中实现多态的机制是什么?
    【参考答案】
    重写,重载
    方法的重写 Overriding 和重载 Overloading 是 Java 多态性的不同表现。
    重写 Overriding 是父类与子类之间多态性的一种表现,重载 Overloading 是一个类中多态性
    的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写
    (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义
    如同被“屏蔽”了。
    果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称
    为方法的重载(Overloading)。Overloaded 的方法是可以改变返回值的类型。
    79、Overload 和 Override 的区别?Overloaded 的方法是否可以改变返回值的类型? 【软
    通动力】
    【参考答案】
    Overload 是重载的意思,Override 是覆盖的意思,也就是重写。
    重载 Overload 表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各
    不相同(即参数个数或类型不同)。
    重写 Override 表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通
    过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义
    的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。子类覆盖父类
    的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可
    以解决父类的一些问题,不能比父类有更多的问题。子类方法的访问权限只能比父类的更大,
    不能更小。如果父类的方法是 private 类型,那么,子类则不存在覆盖的限制,相当于子类
    中增加了一个全新的方法。
    是否可以改变返回值类型,在重载的定义中,与方法是什么类型返回值无关。
    【分析】
    override 可以翻译为覆盖,从字面就可以知道,它是覆盖了一个方法并且对其重
    写,以求达到不同的作用。对我们来说最熟悉的覆盖就是对接口方法的实现,在接口中一般
    只是对方法进行了声明,而我们在实现时,就需要实现接口声明的所有方法。除了这个典型
    的用法以外,我们在继承中也可能会在子类覆盖父类中的方法。在覆盖要注意以下的几点:
    1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;
    2、覆盖的方法的返回值必须和被覆盖的方法的返回一致;
    3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;
    4、被覆盖的方法不能为 private,否则在其子类中只是新定义了一个方法,并没有对其进
    行覆盖。
    overload 对我们来说可能比较熟悉,可以翻译为重载,它是指我们可以定义一些名称相同
    的方法,通过定义不同的输入参数来区分这些方法,然后再调用时,VM 就会根据不同的参
    数样式,来选择合适的方法执行。在使用重载要注意以下的几点:
    1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不
    同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是 fun(int,float),
    但是不能为 fun(int,int));
    2、不能通过访问权限、返回类型、抛出的异常进行重载;
    3、方法的异常类型和数目不会对重载造成影响;
    4、对于继承来说,如果某一方法在父类中是访问权限是 priavte,那么就不能在子类对其
    进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。
    80、ClassLoader 如何加载 class 。
    【参考答案】
    jvm 里有多个类加载,每个类加载可以负责加载特定位置的类,例如,bootstrap 类加
    载负责加载 jre/lib/rt.jar 中的类, 我们平时用的 jdk 中的类都位于 rt.jar 中。
    extclassloader 负责加载 jar/lib/ext/
    .jar 中的类,appclassloader 负责 classpath 指
    定的目录或 jar 中的类。除了 bootstrap 之外,其他的类加载器本身也都是 java 类,它们
    的父类是 ClassLoader。
    81、ArrayList 如何实现插入的数据按自定义的方式有序存放
    【参考答案】
    实现 Comparable 比较接口,并实现 compareTo 方法。排序的方法,取决于 compareTo
    方法中的比较定义的返回值,一般有 3 个返回值:1、-1、0 表示不同的比较结果。
    程序示例:
    class MyBean implements Comparable{
    public int compareTo(Object obj){
    if(! obj instanceof MyBean)
    throw new ClassCastException();
    MyBean other = (MyBean) obj;
    return age > other.age?1:age== other.age?0:-1;
    }
    }
    class MyTreeSet {
    private ArrayList datas = new ArrayList();
    public void add(Object obj){
    for(int i=0;i<datas.size();i++){
    if(obj.compareTo(datas.get(i) != 1){
    datas.add(i,obj);
    }
    }
    }
    }
    82、hashCode 方法的作用?
    【参考答案】
    hashcode 这个方法是用来鉴定 2 个对象是否相等的。hashcode 方法一般用户不会去调
    用,比如在 hashmap 中,由于 key 是不可以重复的,他在判断 key 是不是重复的时候就判断
    了 hashcode 这个方法,而且也用到了 equals 方法。这里不可以重复是说 equals 和 hashcode
    只要有一个不等就可以了!所以简单来讲,hashcode 相当于是一个对象的编码。我们一般
    在覆盖 equals 的同时也要覆盖 hashcode,让他们的逻辑一致。
    83、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 是什么。
    84、Anonymous Inner Class (匿名内部类) 是否可以 extends(继承)其它类,是否可以
    implements(实现)interface(接口)?
    【参考答案】
    可以继承其他类或实现其他接口。不仅是可以,而是必须!
    85、JAVA 语言如何进行异常处理,关键字:throws,throw,try,catch,finally 分别代表什
    么意义?在 try 块中可以抛出异常吗?
    【参考答案】
    Java 使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一
    个对象来表示的,该对象中包含有异常的信息。而 throws\throw\try、catch、finally 就
    是 Java 中用来对异常进行处理的几个关键字,在 Java 编程中规容 Java 编译器强制普通异
    常必须 try…catch 处理或用 throws 声明继续抛给上层调用方法处理,一般异常必须要求被
    捕获和处理,而系统异常可以处理也可以不处理,所以编译器不强制用 try…catch 处理或
    用 throws、throw 声明异常。而 finally 一般与 try 或 try\catch 一起使用做为异常的最后
    处理出口。
    86、同步和异步有何异同,在什么情况下分别使用他们?举例说明。
    【参考答案】
    如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读
    的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。
    当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方
    法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。
    87、当一个线程进入一个对象的一个 synchronized 方法后,其它线程是否可进入此对象的
    其它方法?
    【参考答案】
    分几种情况:
    1.其他方法前是否加了 synchronized 关键字,如果没加,则能。
    2.如果这个方法内部调用了 wait,则可以进入其他 synchronized 方法。
    3.如果其他个方法都加了 synchronized 关键字,并且内部没有调用 wait,则不能。
    4.如果其他方法是 static,它用的同步锁是当前类的字节码,与非静态的方法不
    能同步,因为非静态的方法用的是 this。
    88、线程的基本概念、线程的基本状态以及状态之间的关系
    【参考答案】
    一个程序中可以有多条执行线索同时执行,一个线程就是程序中的一条执行线索,每个
    线程上都关联有要执行的代码,即可以有多段程序代码同时运行,每个程序至少都有一个线
    程,即 main 方法执行的那个线程。如果只是一个 cpu,它怎么能够同时执行多段程序呢?
    这是从宏观上来看的,cpu 一会执行 a 线索,一会执行 b 线索,切换时间很快,给人的感觉
    是 a,b 在同时执行,好比大家在同一个办公室上网,只有一条链接到外部网线,其实,这条
    网线一会为 a 传数据,一会为 b 传数据,由于切换时间很短暂,所以,大家感觉都在同时上
    网。
    状态:就绪,运行,synchronize 阻塞,wait 和 sleep 挂起,结束。wait 必须在 synchronized
    内部调用。
    调用线程的 start 方法后线程进入就绪状态,线程调度系统将就绪状态的线程转为运行状
    态,遇到 synchronized 语句时,由运行状态转为阻塞,当 synchronized 获得锁后,由阻塞转
    为运行,在这种情况可以调用 wait 方法转为挂起状态,当线程关联的代码执行完后,线程
    变为结束状态。
    89、简述 synchronized 和 java.util.concurrent.locks.Lock 的异同 ?
    【参考答案】
    主要相同点:Lock 能完成 synchronized 所实现的所有功能
    主要不同点:Lock 有比 synchronized 更精确的线程语义和更好的性能。synchronized
    会自动释放锁,而 Lock 一定要求程序员手工释放,并且必须在 finally 从句中释放。
    Lock 还有更强大的功能,例如,它的 tryLock 方法可以非阻塞方式去拿锁。
    90、HashMap 和 Hashtable 的区别?【北通网科】
    【参考答案】
    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 的方法是 synchronized 的,而 HashMap 不是,在多个线程访问
    Hashtable 时,不需要自己为它的方法实现同步,而 HashMap 就必须为之提供外同步。
    Hashtable 和 HashMap 采用的 hash/rehash 算法都大概一样,所以性能不会有很大的差异。
    91、List、Set、Map 是否继承自 Collection 接口?
    【参考答案】
    List、Set 是,Map 不是; Map 接口定义的是 Key-Value 存储的特性,与 List 和 Set
    不同,Map 在存储对象时,先要定义这个对象的 key 的值,再存入与这个 key 相对应的 Object,
    Map 集合的取值时根据存入的 key(关键字)来获取与这个关键字对应的对象。
    92、List、Map、Set 三个接口,存取元素时,各有什么特点?
    【参考答案】
    首先,List 与 Set 具有相似性,它们都是单列元素的集合,所以,它们有一个功共同
    的父接口 Collection 接口。Set 里面不允许有重复的元素,即不能有两个相等的对象 。
    List 表示有先后顺序的集合, 当我们多次调用 add(Obj e)方法时,每次加入的对象就
    像火车站买票有排队顺序一样,按先来后到的顺序排序。
    Map 与 List 和 Set 不同,它是双列的集合每次存储时,要存储一对 key/value,不能存
    储重复的 key,这个重复的规则也是按 equals 比较相等。取则可以根据 key 获得相应的
    value,即 get(Object key)返回值为 key 所对应的 value。另外,也可以获得所有的 key
    的结合。
    【分析】
    总结:List 以特定次序来持有元素,可有重复元素。Set 无法拥有重复元素,内部排序。
    Map 保存 key-value 值,value 可多值。上面是大致不同,另外上述 3 个只是接口,而具体
    实现类中,用法大同小异,只是实现的数据结构不同,例如 List 接口下的 LinkedList 主要
    实现了双链表的存储特点,Vector 是线程安全的集合类。
    93、说出 ArrayList,Vector, LinkedList 的存储性能和特性。【大唐动力面试题】
    【参考答案】
    ArrayList 和 Vector 都是使用数组方式存储数据,此数组元素数大于实际存储的数据
    以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动
    等内存操作,所以索引数据快而插入数据慢,Vector 由于使用了 synchronized 方法(线程
    安全),通常性能上较 ArrayList 差,而 LinkedList 使用双向链表实现存储,按序号索引数
    据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度
    较快。
    LinkedList 也是线程不安全的,LinkedList 提供了一些方法,使得 LinkedList 可以被
    当作堆栈和队列来使用。
    94、如何去掉一个 Vector 集合中重复的元素
    【参考答案】
    Vector newVector = new Vector();
    for (int i=0;i<vector.size();i++)
    {
    Object obj = vector.get(i);
    if(!newVector.contains(obj);
    newVector.add(obj);
    }
    还有一种简单的方式,HashSet set = new HashSet(vector);
    95、Set 里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是 equals()?
    它们有何区别?
    【参考答案】
    Set 里的元素是不能重复的,元素重复与否是使用 equals()方法进行判断的。
    96、两个对象值相同(x.equals(y) == true),但却可有不同的 hash code,这句话对不对?
    【参考答案】
    对。
    如果对象要保存在 HashSet 或 HashMap 中,它们的 equals 相等,那么,它们的 hashcode
    值就必须相等。
    如果不是要保存在 HashSet 或 HashMap,则与 hashcode 没有什么关系了,这时候
    hashcode 不等是可以的,例如 arrayList 存储的对象就不用实现 hashcode 方法。
    97、字节流与字符流的区别
    【参考答案】
    要把一片二进制数据数据逐一输出到某个设备中,或者从某个设备中逐一读取一片二进
    制数据,不管输入输出设备是什么,我们要用统一的方式来完成这些操作,用一种抽象的方
    式 进 行描 述 , 这个 抽 象 描述 方 式 起名 为 IO 流 , 对应 的 抽 象类 为 OutputStream 和
    InputStream ,不同的实现类就代表不同的输入和输出设备,它们都是针对字节进行操作的。
    在应用中,经常要完全是字符的一段文本输出去或读进来,用字节流可以吗?计算机中
    的一切最终都是二进制的字节形式存在。对于“中国”这些字符,首先要得到其对应的字节,
    然后将字节写入到输出流。读取时,首先读到的是字节,可是我们要把它显示为字符,我们
    需要将字节转换成字符。由于这样的需求很广泛,人家专门提供了字符流的包装类。
    底层设备永远只接受字节数据,有时候要写字符串到底层设备,需要将字符串转成字节再
    进行写入。字符流是字节流的包装,字符流则是直接接受字符串,它内部将串转成字节,再
    写入底层设备,这为我们向 IO 设别写入或读取字符串提供了一点点方便。
    字符向字节转换时,要注意编码的问题,因为字符串转成字节数组,
    其实是转成该字符的某种编码的字节形式,读取也是反之的道理。
    讲解字节流与字符流关系的代码案例:
    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    public class IOTest {
    public static void main(String[] args) throws Exception {
    String str = “中国人”;
    /FileOutputStream fos = new FileOutputStream(“1.txt”);
    fos.write(str.getBytes(“UTF-8”));
    fos.close();
    /
    /FileWriter fw = new FileWriter(“1.txt”);
    fw.write(str);
    fw.close();
    /
    PrintWriter pw = new PrintWriter(“1.txt”,“utf-8”);
    pw.write(str);
    pw.close();
    /FileReader fr = new FileReader(“1.txt”);
    char[] buf = new char[1024];
    int len = fr.read(buf);
    String myStr = new String(buf,0,len);
    System.out.println(myStr);
    /
    /FileInputStream fr = new FileInputStream(“1.txt”);
    byte[] buf = new byte[1024];
    int len = fr.read(buf);
    String myStr = new String(buf,0,len,“UTF-8”);
    System.out.println(myStr);
    /
    BufferedReader br = new BufferedReader(
    new InputStreamReader(
    new FileInputStream(“1.txt”),“UTF-8”
    )
    );
    String myStr = br.readLine();
    br.close();
    System.out.println(myStr);
    }
    }
    98、java 里面的 io 跟 nio 有什么区别
    【参考答案】
    1、Java NIO 和 IO 之间第一个最大的区别是,IO 是面向流的,NIO 是面向缓冲区的。
    2、Java IO 的各种流是阻塞的。而 Java NIO 的非阻塞模式,使一个线程从某通道发送
    请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会
    获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事
    情。
    3、选择器上,Java IO 无选择器,而 NIO 有选择器,Java NIO 的选择器允许一个单独
    的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线
    程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。
    99、Java 中会存在内存泄漏吗,请简单描述。
    【参考答案】
    所谓内存泄露就是指一个不再被程序使用的对象或变量一直被占据在内存中。java 中
    有垃圾回收机制,它可以保证一对象不再被引用的时候,即对象变成了孤儿的时候,对象将
    自动被垃圾回收器从内存中清除掉。由于 Java 使用有向图的方式进行垃圾回收管理,可以
    消除引用循环的问题,例如有两个对象,相互引用,只要它们和根进程不可达的,那么 GC
    也是可以回收它们的,例如下面的代码可以看到这种情况的内存回收:
    package com.huawei.interview;
    import java.io.IOException;
    public class GarbageTest {
    /**
  • @param args
  • @throws IOException
    */
    public static void main(String[] args) throws IOException {
    // TODO Auto-generated method stub
    try {
    gcTest();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    System.out.println(“has exited gcTest!”);
    System.in.read();
    System.in.read();
    System.out.println(“out begin gc!”);
    for(int i=0;i<100;i++)
    {
    System.gc();
    System.in.read();
    System.in.read();
    }
    }
    private static void gcTest() throws IOException {
    System.in.read();
    System.in.read();
    Person p1 = new Person();
    System.in.read();
    System.in.read();
    Person p2 = new Person();
    p1.setMate(p2);
    p2.setMate(p1);
    System.out.println(“before exit gctest!”);
    System.in.read();
    System.in.read();
    System.gc();
    System.out.println(“exit gctest!”);
    }
    private static class Person
    {
    byte[] data = new byte[20000000];
    Person mate = null;
    public void setMate(Person other)
    {
    mate = other;
    }
    }
    }
    java 中的内存泄露的情况:长生命周期的对象持有短生命周期对象的引用就很可能发生内
    存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致
    不能被回收,这就是 java 中内存泄露的发生场景,通俗地说,就是程序员可能创建了一个
    对象,以后一直不再使用这个对象,这个对象却一直被引用,即这个对象无用但是却无法被
    垃圾回收器回收的,这就是 java 中可能出现内存泄露的情况,例如,缓存系统,我们加载
    了一个对象放在缓存中(例如放在一个全局 map 对象中),然后一直不再使用它,这个对象一
    直被缓存引用,但却不再被使用。
    检查 java 中的内存泄露,一定要让程序将各种分支情况都完整执行到程序结束,然后看某
    个对象是否被使用过,如果没有,则才能判定这个对象属于内存泄露。
    如果一个外部类的实例对象的方法返回了一个内部类的实例对象,这个内部类对象被长期引
    用了,即使那个外部类实例对象不再被使用,但由于内部类持久外部类的实例对象,这个外
    部类对象将不会被垃圾回收,这也会造成内存泄露。
    [] 是对象已不可到达,而内存又没有回收,真正的内存黑洞。
    而 Java 的泄漏,则是因为各种原因,对象对应用已经无用,但一直被持有,一直可到达。
    总结原因无外乎几方面:
  1. 被生命周期极长的集合类不当持有,号称是 Java 内存泄漏的首因。
    这些集合类的生命周期通常极长,而且是一个辅助管理性质的对象,在一个业务事
    务运行完后,如果没有将某个业务对象主动的从中清除的话,这个集合就会吃越来
    Java 高级软件工程师面试题
    第 39 页 共 242 页
    越多内存,可以用 WeakReference,如 WeakHashMap,使得它持有的对象不增加对象
    的引用数。
  2. Scope 定义不对,这个很简单了,方法的局部变量定义成类的变量,类的静态变量
    等。
  3. 异常时没有加 finally{}来释放某些资源,JDBC 时代也是很普遍的事情。
  4. 另外一些我了解不深的原因,如:Swing 里的 Listener 没有显式 remove;内部类持
    有外部对象的隐式引用;Finalizers 造成关联对象没有被及时清空等。
    内存泄漏的检测
    有不少工具辅助做这个事情的,如果手上一个工具也没有,可以用 JDK 自带的小工具:
     看看谁占满了 Heap?
    用 JDK6 的 jmap 可以显示运行程序中对象的类型,个数与所占的大小
    先用 jps 找到进程号,然后 jmap -histo pid 显示或 jmap
    -dump:file=heap_file_name pid 导出 heap 文件
     为什么这些对象仍然可以到达?
    用 jhat(Java Heap Analysis Tool) 分析刚才导出的 heap 文件。
    先 jhat heap_file_name,然后打开浏览器 http://localhost:7000/ 浏览。
    100、Hashcode 和 Equals 的联系
    【参考答案】
    首先 equals()和 hashcode()这两个方法都是从 object 类中继承过来的,主要用来比较对象
    时进行调用。在 object 类中定义如下:
    a)、如果两个对象相同,那么它们的 hashCode 值一定要相同;
    b)、如果两个对象的 hashCode 相同,它们并不一定相同 上面说的对象相同指的是用
    eqauls 方法比较。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值