企业常见面试题汇总Java基础方向附答案

一 Java基础部分

1.1 请列举至少3个JDK安装目录下的可执行程序(javac),并列举几个常用的命令行参数

javac <选项><源文件>  可能的选项包括:  

-g 生成所有调试信息

-g:none 生成无调试信息   

-g:{lines,vars,source} 生成只有部分调试信息  

-O 优化;可能妨碍调试或者增大类文件  

-nowarn 生成无警告   

-verbose 输出关于编译器正在做的信息   

-deprecation 输出使用了不鼓励使用的API的源程序位置  

-classpath <路径> 指定用户类文件的位置  

-sourcepath <路径> 指定输入源文件的位置

-bootclasspath <路径> 覆盖自举类文件的位置  

-extdirs <目录(多个)> 覆盖安装的扩展类的位置  

-d <目录> 指定输出类文件的位置

 

jar {ctxu}[vfm0M] [jar-文件] [manifest-文件] [-C 目录] 文件名 ...选项:  

   -c 创建新的存档

   -t 列出存档内容的列表

   -x 展开存档中的命名的(或所有的)文件  

   -u 更新已存在的存档

   -v 生成详细输出到标准输出上  

   -f 指定存档文件名

   -m 包含来自标明文件的标明信息  

   -0 只存储方式;未用ZIP压缩格式

   -M 不产生所有项的清单(manifest)文件

   -i 为指定的jar文件产生索引信息

 

javadoc [options] [packagenames] [sourcefiles] [classnames] [@files]  -overview<file>读取 HTML 格式的概述文档

   -public 仅显示 public 类和成员

   -protected 显示 protected/public 类和成员(缺省)  

   -package 显示 package/protected/public 类和成员

   -private 显示所有类和成员  

   -help 显示命令行选项  

   -doclet <class> 通过候选 doclet 生成输出  

   -docletpath <path> 指定 doclet 类文件的查找位置  

   -sourcepath <pathlist> 指定源文件的查找位置  

   -classpath <pathlist> 指定用户类文件的查找位置

javah [options] <classes>    其中 [options] 包括:  

-help 打印该帮助信息   -classpath <path> 类的加载路径  

   -bootclasspath <path> 自举类的加载路径

   -d <dir> 输出目录   

   -o <file> 输出文件(仅能使用 -d 或 -o 之一)

   -jni 生成 JNI 风格的头文件(缺省)  

   -old 生成 JDK1.0 风格的头文件

   -stubs 生成 stubs 文件

   -version 打印版本信息  

   -verbose 输出有关本命令所做工作的信息  

   -force 始终写输出文件

1.2 请分析命题:“Java采用自动垃圾回收技术(GC),因此不会出现内存泄露”

对象的建立和放置都是在内存堆栈上面进行的。程序或者其他的对象可以锁定一块堆栈地址来进行其他对象的引用。

当一个对象没有任何引用的时候,Java的自动垃圾回收机制就发挥作用,自动删除这个对象所占用的空间,释放内存以避免内存泄漏。但是内存泄漏并不是就此而完全避免了,当程序员疏忽大意地忘记解除一个对象不应该有的引用的时候,内存泄漏仍然不可避免,不过发生的几率要比不启用垃圾回收机制的C++程序少很多。但总体来讲,自动垃圾回收机制要安全和简单许多。

1.3 简单描述单子模式(单例模式)的各种不同实现方式,极其各自优缺点。请列举至少2种其他的设计模式及应用场景。

  1. /*单例设计模式主要有2种实现方式:懒汉式、饿汉式。 
  2. 他们分别有如下实现: 
  3. 饿汉式: 
  4. //饿汉式单例类.在类初始化时,已经自行实例化   */  
  5. public class Singleton1 {    
  6.     //私有的默认构造子    
  7.     private Singleton1() {}    
  8.     //已经自行实例化     
  9.     private static final Singleton1 single = new Singleton1();    
  10.     //静态工厂方法     
  11.     public static Singleton1 getInstance() {    
  12.         return single;    
  13.     }    
  14. }    
  15. 懒汉式:  
  16. //懒汉式单例类.在第一次调用的时候实例化     
  17. public class Singleton2 {    
  18.     //私有的默认构造子    
  19.     private Singleton2() {}    
  20.     //注意,这里没有final        
  21.     private static Singleton2 single=null;    
  22.     //静态工厂方法     
  23.     public synchronized  static Singleton2 getInstance() {    
  24.          if (single == null) {      
  25.              single = new Singleton2();    
  26.          }      
  27.         return single;    
  28.     }    
  29. }   
  30. /*其他设计模式: 
  31. 1.适配器模式 
  32. 应用场景:比如说在朋友聚会上遇到一个德国人sarsh,可以我不会德语,她不会中文,我只好求助于我的朋友mary了,他作为我和sarsh之间的adapt,让我和sarsh可以交流了。 
  33. 2.装饰模式 
  34. 应用场景:想要自己做礼物送给朋友,拿出去年在华山顶上的照片,在背面写上“最好的礼物”再到街上礼品店买个相框,在找隔壁学美术的朋友设计一个漂亮的盒子装起来,我们都是Decorator。*/ 

1.4 输出结果

public static void main(String[] args)throws Exception{  
  String str = "中国";  
  System.out.println(str.getBytes("UTF-8").length);  
  System.out.println(str.getBytes("GBK").length);  
  System.out.println(str.getBytes("ISO-8859-1").length);  
  System.out.println(new String(str.getBytes("ISO-8859-1"),("ISO-8859-1"));  
  System.out.println(new String(str.getBytes("UTF-8"),("UTF-8"));  
  System.out.println(new String(str.getBytes("GBK"),("GBK"));  
} 

输出结果:
6
4
2
??
中国
中国
 

1.5 使用二分查找法找字符串数组{"a","b","c","d","e","f","g","h"}中"g"元素

public class Query4Half {  
 static int bsearch( String[] a, String v ) {  
  int l, r;  
  l = 0; r = a.length-1;  
  while ( l <= r ) {  
  int m = (l+r)/2;  
  if ( a[m].compareTo(v)==0 ) return m; else  
  if ( a[m].compareTo(v)>0 ) r = m-1; else  
  if ( a[m].compareTo(v)<0 ) l = m+1;  
  }  
  return -1;  
  }  
 public static void main(String[] args) {  
    String str[] = {"a","b","c","d","e","f","g","h"};    
    int bsearch = bsearch(str, "g");  
    System.out.println(bsearch);  
 }  

1.6 Java代码实现一个链表结构

  1. public class MyList<AnyType>  {  
  2. private class Node<AnyType>{  
  3. public  Node<AnyType> pre;  
  4. public  Node<AnyType> next;  
  5. public  AnyType      data;  
  6. public Node(AnyType d, Node<AnyType>p, Node<AnyType> n){}  
  7. public Node(){}  
  8. }  
  9. private int theSize;  
  10. private Node<AnyType> Header;  
  11. private Node<AnyType> Tail;  
  12. public MyList(){}  
  13. public void add(AnyType item){}  
  14. public boolean isEmpty(){}  
  15. public int size(){}  
  16. public AnyType get( int idx){}  
  17. public void print(){}  
  18. }  
  19. /*Node<AnyType>类定义了双向链表中节点的结构,它是一个私有类,而其属性和构造函数都是公有的,这样,其父类可以直接访问其属性,而外部类根本不知道Node类的存在。Data是节点中的数据与,pre指向前一个Node节点,next指向后一个Node节点。其构造函数的实现如下,不解释: 
  20. View Code*/  
  21. public Node(AnyType d, Node<AnyType>p, Node<AnyType> n){  
  22. this.data = d;  
  23. this.pre = p;  
  24. this.next = n;  
  25. }  
  26. public Node(){  
  27.   this.data = null;  
  28.   this.pre = null;  
  29.   this.next = null;  
  30. }  
  31. /*下面我们看一下链表的构造函数实现: 
  32. View Code*/  
  33. public MyList(){  
  34.   theSize = 0;  
  35.   Header = new Node<AnyType>(null,null,null);  
  36.   Tail   =  new Node<AnyType>(null,Header,null);  
  37.   Header.next = Tail;  
  38. }  
  39. /*我们构造了一个带有头、尾节点的双向链表,头节点的Next指向尾节点,为节点的pre指向头节点。链表长度起始为0。 
  40. 继续贴上链表类其它方法的实现,不解释了,应该比较清楚:*/  
  41. //View Code  
  42. public void add(AnyType item){  
  43.   Node<AnyType> aNode = new Node<AnyType>(item,null,null);  
  44.   Tail.pre.next = aNode;  
  45.   aNode.pre = Tail.pre;  
  46.   aNode.next = Tail;  
  47.   Tail.pre = aNode;  
  48.   theSize++;  
  49. }  
  50. public boolean isEmpty(){  
  51.     return ( theSize == 0);  
  52. }  
  53. public int size(){  
  54.    return theSize;  
  55. }  
  56. public AnyType get( int idx){  
  57.   if(idx > theSize-1 || idx < 0)  
  58.      throw new IndexOutOfBoundsException();  
  59.      Node<AnyType> current = new Node<AnyType>(null,Header,null);  
  60.      for(int i = 0; i<idx; i++)  
  61.          current = current.next;  
  62.      return current.data;  
  63. }  
  64. public void print(){  
  65.   Node<AnyType> current = Header.next;  
  66.   while(current.next != null){  
  67.    //如果AnyType是你自己定义 //的数据类型,那么请务必提供  
  68.    //一个toString方法,要么就不  
  69.    //要在链表里实现print方法。  
  70.   System.out.println(current.data.toString());   
  71.       current = current.next;  
  72. }  

1.7 Object类(或子类)的finalize()方法在什么情况下被调用?

当某个对象被系统收集为无用信息的时候,finalize()将被自动调用,但是jvm不保证finalize()一定被调用,也就是说,finalize()的调用是不确定的1.8 

1.8 请列出你所了解的若干个不同类型的runtime exception

NullPointerException - 空指针引用异常

ClassCastException - 类型强制转换异常。

IllegalArgumentException - 传递非法参数异常。

ArithmeticException - 算术运算异常

ArrayStoreException - 向数组中存放与声明类型不兼容对象异常

IndexOutOfBoundsException - 下标越界异常

NegativeArraySizeException - 创建一个大小为负数的数组错误异常

NumberFormatException - 数字格式异常

SecurityException - 安全异常

UnsupportedOperationException - 不支持的操作异常

1.9 数组String[] str和String str分别怎么获取长度?

数组String[] str和String str分别怎么获取长度?

1.10 JAVA实现快速排序算法

  1. public class QuickSort {  
  2.   public static int Partition(int a[],int p,int r){  
  3.  int x=a[r-1];  
  4.   int i=p-1;  
  5.   int temp;  
  6.      for(int j=p;j<=r-1;j++){  
  7.       if(a[j-1]<=x){  
  8.        // swap(a[j-1],a[i-1]);  
  9.        i++;  
  10.        temp=a[j-1];  
  11.        a[j-1]=a[i-1];  
  12.        a[i-1]=temp;  
  13.   }  
  14.      }  
  15.      //swap(a[r-1,a[i+1-1]);  
  16.      temp=a[r-1];  
  17.      a[r-1]=a[i+1-1];  
  18.      a[i+1-1]=temp;  
  19.      return i+1;  
  20.   }  
  21.  public static void QuickSort(int a[],int p,int r){  
  22.   if(p<r){  
  23.    int q=Partition(a,p,r);  
  24.    QuickSort(a,p,q-1);  
  25.    QuickSort(a,q+1,r);  
  26.    }  
  27. }  
  28. public static void main(String[] args){  
  29.   int a[]={23,53,77,36,84,76,93,13,45,23};  
  30.   QuickSort(a,1,10);  
  31.     for (int i=1;i<=10;i++)  
  32.    System.out.println(a[i-1]);  
  33.   } 
  34. }  

1.11 请简单阐述一下Socket通讯原理,以及Socket基于TCP和UDP协议实现的优缺点

Socket通信的原理大致分为以下几个步骤。   

服务器端的步骤如下。  

 (1)建立服务器端的Socket,开始侦听整个网络中的连接请求。

 (2)当检测到来自客户端的连接请求时,向客户端发送收到连接请求的信息,建立与客户端之间的连接。  

 (3)当完成通信后,服务器关闭与客户端的Socket连接。

客户端的步骤如下。  

 (1)建立客户端的Socket,确定要连接的服务器的主机名和端口。

 (2)发送连接请求到服务器,并等待服务器的回馈信息。

 (3)连接成功后,与服务器进行数据的交互。

(4)数据处理完毕后,关闭自身的Socket连接。

TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。

UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快。

1.12 对象封装的原则是什么?

封装原则:隐藏对象的属性和实现细节,仅对外公开接口,并且控制访问级别

在OOP(面向对象)编程中,用类来实现上面的要求。用类实现封装,用封装来实现高内聚,低耦合高聚合是说一个对象的功能都在内部搞定,紧紧地结合在一起

低耦合是说对象之间的依赖要松散,不要牵一发动全身

只有这样,当系统规模扩大时,才能比较方便

1.13 什么是java序列化,如何实现java序列化?

我们有时候将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象,例如,要将java对象存储到硬盘或者传送给网络上的其他计算机,这个过程我们可以自己写代码去把一个java对象变成某个格式的字节流再传输,但是,jre本身就提供了这种支持,我们可以调用OutputStream的writeObject方法来做,如果要让java 帮我们做,要被传输的对象必须实现serializable接口,这样,javac编译时就会进行特殊处理,编译的类才可以被writeObject方法操作,这就是所谓的序列化。需要被序列化的类必须实现Serializable接口,该接口是一个mini接口,其中没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的。

例如,在web开发中,如果对象被保存在了Session中,tomcat在重启时要把Session对象序列化到硬盘,这个对象就必须实现Serializable接口。如果对象要经过分布式系统进行网络传输或通过rmi等远程调用,这就需要在网络上传输对象,被传输的对象就必须实现Serializable接口。

1.14 序列化的作用,应用场景

所谓java对象序列化就是将对象的状态转换成字节流,以后可以通过这些值再生成相同状态的对象!对象序列化是对象持久化的一种实现方法,它是将一个对象的属性和方法转化为一种序列化的格式以用于存储和传输,反序列化就是根据这些保存的信息重建对象的过程。

运用场景1:

Java的JavaBeans:Bean的状态信息通常是在设计时配置的,Bean的状态信息必须被存起来,以便当程序运行时能恢复这些状态信息,这需要将对象的状态保存到文件中,而后能够通过读入对象状态来重新构造对象,恢复程序状态。例如Java.io包有两个序列化对象的类。ObjectOutputStream负责将对象写入字节流,ObjectInputStream从字节流重构对象。

运用场景2:

activiti工作流设置流程变量

1.15 Collection和Collections有什么区别?

Collection是集合类的上级接口,继承与他的接口主要有Set 和List.

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

1.16 String s = new String("abc");请问有几个String对象?分别是

两个或一个,“xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量“xyz”不管出现多少遍,都是缓冲区中的那一个。如果以前就用过‘xyz’直接从缓冲区拿。如果没有就在字符串缓冲区创建这个“xyz”字符串对象,New String每写一遍,就创建一个新的对象。

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

  1. public  class Test {  
  2.   public static void main(String[] args) {  
  3.      System.out.println(new Test().test());;  
  4.      }  
  5.      static int test(){  
  6.             int x = 1;  
  7.             try{  
  8.                return x;  
  9.             }finally{  
  10.                ++x;  
  11.             }  
  12.        }  
  13.   }  
  14.   /*---------执行结果 ---------*/  
  15.   1  

  /*运行结果是1,为什么呢?主函数调用子函数并得到结果的过程,好比主函数准备一个空罐子,当子函数要返回结果时,先把结果放在罐子里,然后再将程序逻辑返回到主函数。所谓返回,就是子函数说,我不运行了,你主函数继续运行吧,这没什么结果可言,结果是在说这话之前放进罐子里的。 */

1.18 java中可见的访问修饰符的含义

public:访问不受限制。

protected:访问仅限于包含类或从包含类派生的类型。只有包含该成员的类以及继承的类可以存取.

Internal:访问仅限于当前程序集。只有当前工程可以存取.

protected internal:访问仅限于当前程序集或从包含类派生的类型。

private:访问仅限于包含类型。只有包含该成员的类可以存取.

1.19 java用什么来判断对象是否是属于某个类或借口的事例?

Instanceof

1.20 Java中,int和Integer有什么区别
 

int是java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况,例如,要想表达出没有参加考试和考试成绩为0的区别,则只能使用Integer。在JSP开发中,Integer的默认为null,所以用el表达式在文本框中显示时,值为空白字符串,而int默认的默认值为0,                 

所以用el表达式在文本框中显示时,结果为0,所以,int不适合作为web层的表单数据的类型。

     在Hibernate中,如果将OID定义为Integer类型,那么Hibernate就可以根据其值是否为null而判断一个对象是否是临时的,如果将OID定义为了int类型,还需要在hbm映射文件中设置其unsaved-value属性为0。

     另外,Integer提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量

1.21 Java中,HashMap和Hashtable的区别?

HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。

     Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。

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

     Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。

就HashMap与HashTable主要从三方面来说。

1.历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现

2.同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步

3.值:只有HashMap可以让你将空值作为一个表的条目的key或value

1.22 Java中,String和StringBuffer的区别?

1, String : 字符串常量,字符串长度不可变!!!

2, StringBuffer : 字符串变量(Synchronized,即线程安全),如果要频繁对字符串内容进行修改,出于效率考虑最好使用StringBuffer,如果想转成String类型,可以调用StringBuffer的toString();StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。append方法始终将这些字符添加到缓冲区的末端;而insert方法则在指定的点添加字符。

3, (*延伸) StringBuilder  字符串变量(非线程安全),这是在JDK5.0新增加的!!!,该对象是一个线程不安全的字符串容器,在单线程操作的情况下此对象可以用于取代StringBuffer!!!

4,(String 和 StringBuffer )两者者之间的区别 :

这两者之间的区别主要区别在性能上,String,每次对存放进String当中的字符串进行更改的时候,都会生成一个新的String对象,然后指针指向该对象(虽然Java不承认自己有指针这回事),而一旦当产生的没有引用指向对象过多的时候 ,这个时候GC就会出动,对其进行清理,这个时候,性能就会有所降低!!!而使用 StringBuffer的时候,每次都会对该对象本身进行操作,而不是去创建一个新的对象,所以在多数情况下还是推荐使用该对象!!!

但是某些特殊的情况下,使用String 并不会比StringBuffer慢!!!

例如 : String str = "String1" + "String2";&& StringBuffer sb =

new  StringBuffer(); sb.append("String1").append("String2");

在这里的String str = "String1" + "String2"实际上被翻译成了 str = "String1String2";

1.23 Thread和Runnable有什么不同?

首先,Java 中Thread 和 Runnable是实现并发线程的两种方式!!!,

通过两者中的任意一个都可以达到线程并发的目的!!!

区别 :

0,Thread 是一個 Class,Runnable 是一個 interface!!!

1,通过extends Thread,可获得start(), sleep(), 并覆盖run(), 使用时直接用start(),但有时不太方便通过继承(extends)而进行多线程,例如已继承了其它Class(Java 不允许多重继承)时,就应该实现(implements) Runnable写多线程程序。

2,注意,implements Runnable创建的只有run()方法而没有start(),因此要利用其它机制来启动。这要创建两个对象,

第一个是Runnable的,

第二个是Thread的,然后把第一个当成参数传给第二个!!!

3,由下面的程序可以看出,实现Runnable的多线程程序要比,继承Thread的多线程程序灵活的多!!!

4,这里还有一点,就是说使用Runnable实现多线程可以达到资源共享目的,让多个Thread对象接收同一个Runnable实现类的参数,这样就是多个线程操作同一块资源!!!

例如 :

  1. //Runnable 接口的多线程程序举例!!!  
  2. private class RunnableThread implements Runnable{  
  3. /*这个方法中写,多线程执行的程序!!!,因为这里是实现了Runnable所以就算再去继承其他的class也不会违反java成不能多继承的规定!!!*/  
  4.   public void run(){   
  5.   }  
  6. }  
  7. /*通过将Runnable的实现类作为参数传递给一个Thread对象,然后通过开启Thread对象,就能让其执行自己复写的方法,并且是并发操作!!!*/  
  8.    Thread runnThread = new Thread(new RunnableThread());  
  9.    RunnThread.start();   
  10.   /*1,继承自Thread类的多线程程序
  11.    private class GenThread extends Thread  {  
  12.       //这个方法中写,多线程需要执行的方法!!!  
  13.        public void run() { 
  14.         }  
  15.    }                                             
  16.    Thread theGenThread = new GenThread();  

   theGenThread.start();  

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

1,GC : 垃圾回收 (GarbageCollection),Java的内存管理,其内置的垃圾回收,是Java语言的优秀成果,它允许开发者创建新的对象不需要明确内存分配和释放,因为垃圾回收器自动回收内存当中的对象。

2,垃圾收集释放从手工处理内存释放的程序员。其结果是,某些类别的缺陷被消除或显着减少:这也正是Java的特点(相对于C++来说,程序员不再需要通过痛苦的记忆哪里的内存是释放掉的,而哪一些是没有释放掉的)

内存不安全释放的问题 :

1,当一块内存被释放,同时还存在着指向它,而那些指针中的一个被废弃发生。届时内存可能已被重新分配到其他使用,具有不可预知的结果。

2,当程序试图发生释放的内存已被释放,并可能已经被再次分配的区域。

3,某些种类的内存泄漏,其中一个程序无法释放由已成为对象占用的内存可达,从而导致内存消耗殆尽。(垃圾收集通常不处理的数据是可到达的无界积累,但实际上将不被使用的程序)

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

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

1.26 如何把一段逗号分隔的字符串转换成一个数组?
 

  1. //方式一:使用String的split 方法    
  2.     public static String[] convertStrToArray(String str){    
  3.         String[] strArray = null;    
  4.         strArray = str.split(",");    
  5.         return strArray;    
  6.     }    
  7. //方式二:使用StringTokenizer实现    
  8.     //api说明:StringTokenizer 是出于兼容性的原因而被保留的遗留类    
  9.     //(虽然在新代码中并不鼓励使用它)。建议所有寻求此功能的人使用    
  10.     //String 的 split 方法或 java.util.regex 包    
  11.     public static String[] convertStrToArray2(String str){    
  12.         StringTokenizer st = new StringTokenizer(str,",");    
  13.         String[] strArray = new String[st.countTokens()];    
  14.         int i=0;    
  15.         while(st.hasMoreTokens()){    
  16.             strArray[i++] = st.nextToken();    
  17.         }    
  18.         return strArray;    

    }  

1.27 HashMap和Hashtable的区别
 

1、同步或线程安全:这是两者最重要的区别。HashMap的是不同步的,不是线程安全的,另一方面,Hashtable是线程安全的,同步的。

1-1、何时使用HashMap:答案是,如果您的应用程序不需要任何多线程任务,换句话说HashMap

的是对于非线程安全应用程序的更好的选择。哈希表应当在多线程应用中使用。

2、null键和空值:HashMap是允许空键空值的,而Hashtable是不允许空键空值的。

3、迭代器类型:HashTable使用Enumeration,HashMap使用Iterator。

4、性能:HashMap因为是线程不安全的,效率要比Hashtable高。

5、Hashtable是Dictionary类现在是在JDK 1.7过时的子类,因此,它已不再使用。

hashmap与hashtable
Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现 
HashMap允许将null作为一个entry的key或者value,而Hashtable不允许 
还有就是,HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。 
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在 
多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 
就必须为之提供外同步

1.28 java堆和栈的区别

Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程,主要存放线程执行过程中的局部变量,方法的返回值,基本类型的变量(,int, short, long, byte, float, double, boolean, char)以及方法调用的上下文。栈空间随着线程的终止而释放,栈的优势是,存取速度比堆要快,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈有一个很重要的特殊性,就是存在栈中的数据可以共享。

Java中堆是由所有的线程共享的一块内存区域,堆用来保存各种JAVA对象,比如数组,线程对象等,

java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等 指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时 动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

1.29 当一个线程进入一个对象的synchronized方法后,其他线程是否可进入此对象的其他方法?为什么?

分情况而定:

     1.其他方法前是否加了synchronized关键字,如果没加,则能。

     2.如果这个方法内部调用了wait,则可以进入其他synchronized方法。

     3.如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则能。

     4.如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this

1.30 99乘法表

  1. /*主要是利用双层for循环来实现,外层循环9次,内层每次循环的次数与外层是第几次循环有关,还要考虑字符串的拼接及换行和制表符的问题,具体代码如下:*/  
  2. public class s99{  
  3.  public static void main(String[] args){  
  4.   for (int i=1;i<=9;i++) {  
  5.    for (int j=1;j<=i;j++){  
  6.    System.out.print(i+"*"+j+"="+(i*j)+"\t");  
  7.    }  
  8.    System.out.print("\n");  
  9.   }  
  10.  }  
  11. }  

1.31 常用的字符转码方式什么?举例说明

1.escape方法对String对象编码,escape方法返回一个包含了"转义序列"的字符串值。

除了ASCII字母和数字,以及这几个符号 *+-/.@_外(共有10+52+7=69个字符不会被编码),

其他所有的字符都会被转义序列替换,标准ASCII码内的字符(0-127)和扩展的ASCII码内

的字符(128-255)都用%xx编码形式代替。字符值大于255的以unicode%uxxxx格式存储。

注意 :escape方法不能够用来对统一资源标示符URI进行编码,因为=&?#等会被编码.

对URI编码应使用encodeURI,对URI参数用encodeURIComponent方法。

2.encodeURI除了ASCII字母和数字,以及这几个符号 *+-/.@_!#$&\'(),:=?~外(共有10+52+20=82个字符不会被编码),

其他所有的字符都会被转义序列替换,标准ASCII码内的字符(0-127)和扩展的ASCII码内

的字符(128-255)都用%xx编码形式代替。字符值大于255的以utf-8多字节%xx格式存储。

在URI中有特殊意义的字符如?=&等不会被编码。

3.encodeURIComponent除了ASCII字母和数字,以及这几个符号 *-_.~!'()外(共有10+52+9=71个字符不会被编码),其他所有的字符都会被转义序列替换,标准ASCII码内的字符(0-127)和扩展的ASCII码内的字符(128-255)都用%xx编码形式代替。字符值大于255的以utf-8多字节%xx格式存储。可以看到?=&等在URI中有特殊意义的字符也会被编码。

encodeURIComponent方法在编码单个URIComponent(指请求参数)应当是最常用的,

它可以将参数中的中文、特殊字符进行转义,而不会影响整个URL。

1.32 如何给tomcat指定大小的内存

Tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,需要调大。有以下几种方法可以选用:

第一种方法:

Windows下,在文件/bin/catalina.bat,Unix下,在文件/bin/catalina.sh的前面,增加如下设置:

JAVA_OPTS='-Xms【初始化内存大小】-Xmx【可以使用的最大内存】'

需要把这个两个参数值调大。例如:

JAVA_OPTS='-Xms256m-Xmx512m'

表示初始化内存为256MB,可以使用的最大内存为512MB。

第二种方法:环境变量中设

变量名:JAVA_OPTS

变量值:-Xms512m-Xmx512m

第三种方法:前两种方法针对的是bin目录下有catalina.bat的情况(比如直接解压的Tomcat等),但是有些安装版的Tomcat下没有catalina.bat,这个时候可以采用如下方法,当然这个方法也是最通用的方法:

打开tomcatHome/\bin/\tomcat5w.exe,点击Java选项卡,然后将会发现其中有这么两项:Initialmemorypool和Maximummemorypool.Initialmemorypool这个就是初始化设置的内存的大小。Maximummemorypool这个是最大JVM内存的大小设置完了就按确定然后再重启TOMCAT你就会发现tomcat中jvm可用的内存改变了。

1.33 final,finally,finalize的区别

1.final为关键字,final定义基本类型变量时,要求变量初始化必须在声明时或者构造函数中,不能用于其它地方。该关键字定义的常量,除了初始化阶段,不能更改常量的值; final定义对象的引用,该引用的初始化与定义常量时的要求一致;该关键字定义的对象内容可以改变,但是引用指向的地址不能改变;final修饰类时无法被其他任何类继承。

2.finalize()方法在Object中进行了定义,用于在对象“消失”时,由JVM进行调用用于对对象进行垃圾回收。

3.finally为区块标志,用于try语句中,表示必须运行的区块部分。

1.34 Collection和Collections的区别

Collection是集合类的上级接口,继承与他的接口主要有Set 和List.

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

1.35 组合和聚合的区别

聚合:表示两个对象之间是整体和部分的关系,部分的生命周期可以超越整体。电脑和鼠标的关系

组合:表示两个对象之间是整体和部分的强关系,部分的生命周期不能超越整体,或者说不能脱离整体而存在。组合的关系“部分”是不能再整体之间进行共享的。如人跟眼睛

1.36 关联和依赖的区别

关联:简单而言,如果一个类作为了另外一个类的属性,那一定是关联关系。但是聚合是一种特殊的关联,而组合

又是一种特殊的聚合。一般的关联我们认为是平级、无整体部分关系的,如朋友关系。

依赖:对象之间的临时关系,临时性体现在不超越方法的周期。简单地说,在方法使用到的,如参数类,就一定是

依赖关系

1.37 JDK中用到的设计模式

1、创建模式

Singleton(单例):只允许创建一个实例

  1. Runtime.getRuntime();  
  2. java.awt.Toolkit.getDefaultToolkit();  
  3. java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();  
  4. java.awt.Desktop.getDesktop();  

Abstract factory(抽象工厂):创建一组有关联的对象实例

  1. java.util.Calendar.getInstance();  
  2. java.util.Arrays.asList();  
  3. java.util.ResourceBundle.getBundle(String baseName);  
  4. java.sql.DriverManager.getConnection(String url);  
  5. java.sql.Connection.createStatement();  
  6. java.sql.Statement.executeQuery(String sql);  
  7. java.text.NumberFormat.getInstance();  
  8. javax.xml.transform.TransformerFactory.newInstance();  

Factory(工厂方法):按照需求返回一个类型的实例

  1. java.lang.Proxy.newProxyInstance();  
  2. java.lang.Object.toString();  
  3. java.lang.Class.newInstance();  
  4. java.lang.reflect.Array.newInstance();  
  5. java.lang.reflect.Constructor.newInstance();  
  6. java.lang.Boolean.valueOf(String s);  
  7. java.lang.Class.forName(String className);  

Builder(建造者):主要用来简化一个复杂的对象的创建

  1. java.lang.StringBuilder.append(Object obj);  
  2. java.lang.StringBuffer.append(Object obj);    
  3. java.sql.PreparedStatement    
  4. javax.swing.GroupLayout.Group.addComponent();  

Prototype(原型):使用自己的实例创建另一个实例

  1. java.lang.Object.clone();  
  2. java.lang.Cloneable;  
  1. 结构模式

Adapter(适配器):个接口或是类变成另外一种

  1. java.util.Arrays.asList();  
  2. javax.swing.JTable(TableModel)    
  3. java.io.InputStreamReader(InputStream)    
  4. java.io.OutputStreamWriter(OutputStream)    
  5. javax.xml.bind.annotation.adapters.XmlAdapter.marshal();  
  6. javax.xml.bind.annotation.adapters.XmlAdapter.unmarshal();  

Composite(组合):让使用者把单独的对象和组合对象混用

  1. javax.swing.JComponent.add(Component comp);  
  2. java.awt.Container.add(Component comp);   
  3. java.util.Map.putAll(Map m);  
  4. java.util.List.addAll(Collection c);  
  5. java.util.Set.addAll(Collection c);  

Decorator(装饰器):为一个对象动态的加上一系列的动作,而不需要因为这些动作的不同而产生大量的继承类

  1. java.io.BufferedInputStream(InputStream);  
  2. java.io.DataInputStream(InputStream);  
  3. java.io.BufferedOutputStream(OutputStream);  
  4. java.util.zip.ZipOutputStream(OutputStream);  
  5. java.util.Collections.checkedList(List list, Class type) ;   

Facade(门面):一个简单的接口包状一组组件,接口,抽象或是子系统。

  1. java.lang.Class    
  2. javax.faces.webapp.FacesServlet  

Flyweight(共享元):有效率地存储大量的小的对象

  1. java.lang.Integer.valueOf(int)    
  2. java.lang.Boolean.valueOf(boolean)    
  3. java.lang.Byte.valueOf(byte)  
  4. java.lang.Character.valueOf(char

Proxy(代理):用一个简单的对象来代替一个复杂的对象

  1. java.lang.reflect.Proxy  
  1. 行为模式

Chain of Responsibility(责任链):一个对象在一个链接传递直到被处理

  1. java.util.logging.Logger.log()   
  2. javax.servlet.Filter.doFilter() 

Command(命令):将一系列的命令封装成在一个类中

  1. java.lang.Runnable  
  2. javax.swing.Action  

Interpreter(解释器):定义语言的文法 ,并且建立一个解释器来解释该语言中的句子

  1. java.util.Pattern  
  2. java.text.Normalizer  
  3. java.text.Format  

Iterator(迭代器):对象遍历

  1. java.util.Iterator  
  2. java.util.Enumeration  

Mediator(中介):用一个中介对象来封装一系列关于对象交互行为

  1. java.util.Timer  
  2. java.util.concurrent.Executor.execute()  
  3. java.util.concurrent.ExecutorService#submit()  
  4. java.lang.reflect.Method.invoke()  

Memento(快照):保存另外一个对象内部状态拷贝的对象

  1. java.util.Date  
  2. java.io.Serializable  

Observer(观察者):事件监听器

  1. java.util.EventListener  
  2. javax.servlet.http.HttpSessionBindingListener  
  3. javax.servlet.http.HttpSessionAttributeListener  
  4. javax.faces.event.PhaseListener  

State(状态):不同的状态,不同的行为;或者说,每个状态有着相应的行为.

  1. java.util.Iterator  
  2. javax.faces.lifecycle.LifeCycle.execute() 

Strategy(策略):定义一系列的算法,把这些算法一个个封装成单独的类

  1. java.util.Comparator.compare()  
  2. javax.servlet.http.HttpServlet   
  3. javax.servlet.Filter.doFilter()  

Template(模板):定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中

  1. java.util.Collections.sort()  
  2. java.io.InputStream.skip()   
  3. java.io.InputStream.read()  
  4. java.util.AbstractList.indexOf()   

Visitor(访问者):作用于某个对象群中各个对象的操作. 它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作.

  1. javax.lang.model.element.Element
  2. javax.lang.model.element.ElementVisitor  
  3. javax.lang.model.type.TypeMirror
  4. javax.lang.model.type.TypeVisitor    

1.38 在Java中,什么是interface,abstractclassInterfaceabstract class有何区别?

interface : java中的接口是,程序的规范,当中可以定义常量和抽象方法(它允许使用者确定方法名,参数列表和返回值,但是没有方法体),接口提供了形式,但是没有提供具体的实现。

abstract Class:抽象类,抽象类是接口和普通类之间的一种实现方式,因为不能总是使用纯接口但是又必须使用抽象方法的时候,抽象类就成了用于此目的的重要工具。

abstract method:仅有声明而没有方法体的方法,就成为抽象方法,包含抽象方法的类就叫抽象类,这个时候的类就不需要加上abstract的限定,否则编译错误。

Interface和abstract class的区别:

    1. 接口中不允许有方法实现,抽象类中,可以存在抽象或者非抽象方法。
    2. 接口中只能有静态的不可修改的成员(static final)。
    3. 因为java只允许单集成,所以抽象作为类型定义,受到了极大的限制,但是接口可以多实现。
    4. 设计理念不同,abstract class 表示的是“is-a”关系,而interface表示“like-a”关系。
    5. 抽象类中的变量默认是friendly型,其值可以在子类中重新定义,也可以重新赋值。
    6. 接口中的方法默认都是public abstract类型的。

1.39 StringStringBuffer有什么区别?

  1. String是字符串常量,字符串长度不可变!
  2. StringBuffer字符串变量(Synchronized,线程安全),如果要频繁对字符串内容进行修改,处于效率考虑最好使用StringBuffer,如果想转换成String类型,可以调用StringBuffer的toString();StringBuffer上的主要操作是append和insert方法,可重载这些方法,已接受任意类型的数据。
  3. (*延伸)StringBuilder字符串变量(非现场安全),这是JDK5.0新增,该对象是一个线程不安全的字符串容器,在单线程操作的情况下此对象可以用于取代StringBuffer。
  4. 两者区别:主要体现在性能上,每次对存放进String当中的字符串进行更改的时候,都会生成一个新的String对象,然后指针指向该对象,而一旦当产生的没有引用指向对象过多的时候,GC就会回收,降低性能;而使用StringBuffer的时候,每次都会对该对象本身进行操作,而不是去创建一个新的对象,所以在多数情况下还是推荐使用。
  5. String某些情况下不比StringBuffer慢;如:

String str = "string1"+"string2";  

StringBuffer sb = new StringBuffer();  

sb.append("string1").append("string2");  

在这里String str = "string1"+"string2";<==> str = "string1string2";

1.40 说明链表、哈希表数组的特点

  1. 链表是一种物理存储单元上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
    1. 链表的存储在内存中可以是非连续性的,因为链表结构可以通过自身节点中的数据域指针域来找到下一个节点。
    2. 对链表进行删除插入操作时,只需要将其指针域进行修改即可(相对于数组来说内部操作更便捷)
    3. 链表本身不存在下标,所有查询效率略低。

*:一般而言进行删除修改等操作的时候使用的是链表结构,而查询的时候则使用数组结构

*:Java中由于linked*的内部实现是采用链表结构。

  1. 散列表(Hashtable,也叫哈希表),是根据关键码值(Key Value)而直接进行访问的数据结构
    1. 哈希表最大的优势,就是把数据的存储和查询消耗的时间大大降低,几乎可以看成是常数时间。损失的代价仅仅是消耗比较多的内存,然而在当前可利用内存越来越多的情况下,用空间换时间的做法是相当值得的。而且编码也比较容易。
    2. 散列表查询速度快的原因:
      1. 将键值保存在某处,以便于能很快找到(数组中,这里保存的不是键本身而是键的信息,数组的下标就是这个对象的hashCode)
      2. 查询的过程就变成了,首先生产该对象的HashCode,然后查询数组,,然后再去保存值的list当中查询
  1. 数组是一种物理存储单元上连续,顺序的存储结构,可以通过下标访问数组元素。
    1. 数组的保存效率高并且具备保存基本类型的能力。
    2. 数组是一种简单的线性序列,这使得访问速度非常快。
    3. 数组在定义时其大小被固定,并且在其声明周期中不可改变。
    4. 数组的查询速度,相对来说是比较快的,因为可以对其索引进行快速便利。

1.41 ArrayList、LinkedList和Vector的区别

ArrayList:底层数据结构是数组,运行所有元素,包括null,查询快,增删慢,线程不安全(非同步),效率高!

Vector:底层数据结构是数组,查询快,增删慢,线程安全(同步),效率低~!

LinkedList:底层数据结构是链表,允许null元素,查询慢,增删快,线程不安全(非同步),效率高!

1.42 多线程有几种实现方法,都是什么?启动一个线程调用的是哪个方法

Java中Thread和Runnable是实现并发线程的两种方式!

区别:

    1. Thread是一个Class,Runnable是一个interface
    2. 通过extends Thread,可获得start(),sleep(),并覆盖run(),使用时直接调用start()方法即可,但是有时不方便通过继承而进行多线程,如已经继承其他的class时,就需要实现实现Runnable接口了,因为Java是不允许多继承形式的出现,但是可以使用多实现。
    3. 而implement Runnable接口的时候,创建的只有run()方法,而没有start()方法,因此要利用其他机制来启动。这就要创建两个对象,第一个是Runnable的,第二个是Thread的,然后把第一个当成参数传递给第二个;
    4. *:使用Runnable实现多线程可以到达资源共享的目的,让多个Thread对象接收同一个Runnable实现类的参数,这样就是多个线程同时操作同一块资源。
private class RunnableThread implements Runnable {  

//这个方法中写,多线程执行的程序!!!,因为这里是实现了Runnable所以就算再去继承其他的class也不会违反java成不能多继承的规定!!!  

    public void run(){   

 

    }  

}  

//通过将Runnable的实现类作为参数传递给一个Thread对象,然后通过开启Thread对象,就能让其执行自己复写的方法,并且是并发操作!!!  

    Thread runnThread = new Thread(new RunnableThread());  

          RunnThread.start();   

          //1,继承自 Thread类的多线程程序!!!  

        private class GenThread extends Thread{  

        //这个方法中写,多线程需要执行的方法!!!  

            public void run() {  

                                  

            }  

        }   

        Thread theGenThread = new GenThread();  

        theGenThread.start();  

1.43 Class.forName()作用?

  1. 装载一个类并且对其进行实例化的操作。
  2. 装载过程中使用到的类加载器是当前类。

*:为了详细描述,Class.forName()方法,这里使用classLoader.loadClass()进行对比描述

    1. Class.forName(String className)使用装载当前类的类装载器来装载制定的类,因为class.forName(String name)

方法内部调用了Class.forName(className,true,this.getClass().getClassLoader())方法。

    1. classLoader.loadClass(StringclassName,boolean resolve);需要手动制定装载器的实例。
    2. Class.forName(className)装载的class已经被实例化,classLoader.loadClass().则只是将信息装载给JVM。
    3. 在JDBC中Class.forName(“com.mysql.jdbc.Driver”),如果换成getClass().getClassLoader().loadClass(“com.mysql.jdbc.Driver”),就不可以,因为它只是想JVM装载了Driver的类信息,但是没有实例化,也就不能执行相应的操作,因为Driver是需要被初始化才能被使用的。

1.44 一个类是否可以继承多个接口?

在Java中接口是允许多实现的,接口和接口之间可以进行多实现,大部分的类也都是实现多个接口。

1.45 一个类是否可以继承多个超类?

类的继承,同一层次结构只能继承一个类。

1.46 接口是否可继承接口?

接口之间不能实现,因为接口本身就是抽象的,但是接口可以继承接口的,并且可以进行多继承(因为抽象,所以不担心方法的冲突)

1.47 抽象类是否可以实现(implement)接口?

可以,抽象类也是类,类是可以实现接口的。

  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纵然间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值