这套面试题主要目的是帮助那些还没有 java 软件开发实际工作经验, 而正在努力寻找 java 软件开发工作的朋友在笔试时更好地赢得笔试和面试.
1, 一个 ".java" 源文件中是否可以包括多个类(不是内部类)? 有什么限制?
可以有多个类, 但只能有一个 public 的类, 并且 public 的类名必须与文件名相一致.
2,Java 有没有 goto?
java 中的保留字, 现在没有在 java 中使用.
3, 说说 & 和 && 的区别.
& 和 && 都可以用作逻辑与的运算符, 表示逻辑与(and), 当运算符两边的表达式的结果都为 true 时, 整个运算结果才为 true, 否则, 只要有一方为 false, 则结果为 false.
&& 还具有短路的功能, 即如果第一个表达式为 false, 则不再计算第二个表达式.
& 还可以用作位运算符, 当 & 操作符两边的表达式不是 boolean 类型时,& 表示按位与操作, 我们通常使用 0x0f 来与一个整数进行 & 运算, 来获取该整数的最低 4 个 bit 位.
4, 在 JAVA 中如何跳出当前的多重嵌套循环?
在 Java 中, 要想跳出多重循环, 可以在外面的循环语句前定义一个标号, 然后在里层循环体的代码中使用带有标号的 break 语句, 即可跳出外层循环.
5,switch 语句能否作用在 byte 上, 能否作用在 long 上, 能否作用在 String 上?
在 switch(expr1)中, expr1 只能是一个整数表达式或者枚举常量(更大字体), 整数表达式可以是 int 基本类型或 Integer 包装类型, 由于, byte,short,char 都可以隐含转换为 int, 所以, 这些类型以及这些类型的包装类型也是可以的. 显然, long 和 String 类型都不符合 switch 的语法规定, 并且不能被隐式转换成 int 类型, 所以, 它们不能作用于 swtich 语句中.
6,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 编译器会对它进行特殊处理, 因此可以正确编译.
7,char 型变量中能不能存贮一个中文汉字? 为什么?
char 型变量是用来存储 Unicode 编码的字符的, unicode 编码字符集中包含了汉字, 所以, char 型变量中当然可以存储汉字啦. 不过, 如果某个特殊的汉字没有被包含在 unicode 编码字符集中, 那么, 这个 char 型变量中就不能存储这个特殊汉字. 补充说明: unicode 编码占用两个字节, 所以, char 类型的变量也是占用两个字节.
8, 用最有效率的方法算出 2 乘以 8 等於几?
2 << 3,
因为将一个数左移 n 位, 就相当于乘以了 2 的 n 次方, 那么, 一个数乘以 8 只要将其左移 3 位即可, 而位运算 CPU 直接支持的, 效率最高, 所以, 2 乘以 8 等於几的最效率的方法是 2 << 3.
9, 使用 final 关键字修饰一个变量时, 是引用不能变, 还是引用的对象不能变?
使用 final 关键字修饰一个变量时, 是指引用变量不能变, 引用变量所指向的对象中的内容还是可以改变的.
10,"==" 和 equals 方法究竟有什么区别?
== 操作符专门用来比较两个变量的值是否相等, 也就是用于比较变量所对应的内存中所存储的数值是否相同, 要比较两个基本类型的数据或两个引用变量是否相等, 只能用 == 操作符.
equals 方法是用于比较两个独立对象的内容是否相同, 就好比去比较两个人的长相是否相同, 它比较的两个对象是独立的.
11, 静态变量和实例变量的区别?
在语法定义上的区别: 静态变量前要加 static 关键字, 而实例变量前则不加.
在程序运行时的区别: 实例变量属于某个对象的属性, 必须创建了实例对象, 其中的实例变量才会被分配空间, 才能使用这个实例变量. 静态变量不属于某个实例对象, 而是属于类, 所以也称为类变量, 只要程序加载了类的字节码, 不用创建任何实例对象, 静态变量就会被分配空间, 静态变量就可以被使用了. 总之, 实例变量必须创建对象后才可以通过这个对象来使用, 静态变量则可以直接使用类名来引用.
12, 是否可以从一个 static 方法内部发出对非 static 方法的调用?
不可以. 因为非 static 方法是要与对象关联在一起的, 必须创建一个对象后, 才可以在该对象上进行方法调用, 而 static 方法调用时不需要创建对象, 可以直接调用. 也就是说, 当一个 static 方法被调用时, 可能还没有创建任何实例对象, 如果从一个 static 方法中发出对非 static 方法的调用, 那个非 static 方法是关联到哪个对象上的呢? 这个逻辑无法成立, 所以, 一个 static 方法内部发出对非 static 方法的调用.
13,Integer 与 int 的区别
Integer 是 java 为 int 提供的封装类. int 的默认值为 0, 而 Integer 的默认值为 null, 即 Integer 可以区分出未赋值和值为 0 的区别, int 则无法表达出未赋值的情况.
14,Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math 类中提供了三个与取整有关的方法: ceil,floor,round, 这些方法的作用与它们的英文名称的含义相对应, 例如, ceil 的英文意义是天花板, 该方法就表示向上取整, Math.ceil(11.3)的结果为 12,Math.ceil(-11.3)的结果是 - 11;floor 的英文意义是地板, 该方法就表示向下取整, Math.ceil(11.6)的结果为 11,Math.ceil(-11.6)的结果是 - 12; 最难掌握的是 round 方法, 它表示 "四舍五入", 算法为 Math.floor(x+0.5), 即将原来的数字加上 0.5 后再向下取整, 所以, Math.round(11.5)的结果为 12,Math.round(-11.5)的结果为 - 11.
15, 请说出作用域 public,private,protected, 以及不写时的区别
这四个作用域的可见范围如下表所示.
说明: 如果在修饰的元素上面没有写任何访问修饰符, 则表示 friendly.
作用域当前类同一 package 子孙类其他 package
public√√√√
protected√√√*
friendly√√**
private√***
16,Overload 和 Override 的区别.
Overload 是重载的意思, Override 是覆盖的意思, 也就是重写.
重载 Overload 表示同一个类中可以有多个名称相同的方法, 但这些方法的参数列表各不相同(即参数个数或类型不同).
重写 Override 表示子类中的方法可以与父类中的某个方法的名称和参数完全相同, 通过子类创建的实例对象调用这个方法时, 将调用子类中的定义方法, 这相当于把父类中定义的那个完全相同的方法给覆盖了, 这也是面向对象编程的多态性的一种表现.
17, 构造器 Constructor 是否可被 override?
构造器 Constructor 不能被继承, 因此不能重写 Override, 但可以被重载 Overload.
18, 接口是否可继承接口? 抽象类是否可实现 (implements) 接口? 抽象类是否可继承具体类(concrete class)? 抽象类中是否可以有静态的 main 方法?
接口可以继承接口. 抽象类可以实现 (implements) 接口, 抽象类是否可继承具体类. 抽象类中可以有静态的 main 方法.
19, 写 clone()方法时, 通常都有一行代码, 是什么?
clone 有缺省行为, super.clone(); 因为首先要把父类中的成员复制到位, 然后才是复制自己的成员.
20, 面向对象的特征有哪些方面
面向对象的编程语言有封装, 继承, 抽象, 多态等 4 个主要的特征.
21,java 中实现多态的机制是什么?
靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象, 而程序调用的方法在运行期才动态绑定, 就是引用变量所指向的具体实例对象的方法, 也就是内存里正在运行的那个对象的方法, 而不是引用变量的类型中定义的方法.
22,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. 一个类可以实现多个接口, 但只能继承一个抽象类.
23,abstract 的 method 是否可同时是 static, 是否可同时是 native?
abstract 的 method 不可以是 static 的, 因为抽象的方法是要被子类实现的, 而 static 与子类扯不上关系!
native 方法表示该方法要用另外一种依赖平台的编程语言实现的, 不存在着被子类实现的问题, 所以, 它也不能是抽象的, 不能与 abstract 混用.
24, 什么是内部类?
内部类就是在一个类的内部定义的类, 内部类中不能定义静态成员(静态成员不是对象的特性, 只是为了找一个容身之处, 所以需要放到一个类中而已.
25,Anonymous Inner Class (匿名内部类) 是否可以 extends(继承)其它类, 是否可以 implements(实现)interface(接口)?
可以继承其他类或实现其他接口. 不仅是可以, 而是必须!
26,String 是最基本的数据类型吗?
基本数据类型包括 byte,int,char,long,float,double,boolean 和 short.
java.lang.String 类是 final 类型的, 因此不可以继承这个类, 不能修改这个类. 为了提高效率节省空间, 我们应该用 StringBuffer 类
27,String s = "Hello";s = s + "world!"; 这两行代码执行后, 原始的 String 对象中的内容到底变了没有?
没有. 因为 String 被设计成不可变 (immutable) 类, 所以它的所有对象都是不可变对象.
28, 是否可以继承 String 类?
String 类是 final 类故不可以继承.
29,String s = new String("xyz"); 创建了几个 String Object? 二者之间有什么区别?
两个或一个,"xyz" 对应一个对象, 这个对象放在字符串常量缓冲区, 常量 "xyz" 不管出现多少遍, 都是缓冲区中的那一个. New String 每写一遍, 就创建一个新的对象, 它一句那个常量 "xyz" 对象的内容来创建出一个新 String 对象. 如果以前就用过'xyz', 这句代表就不会创建 "xyz" 自己了, 直接从缓冲区拿.
30,String 和 StringBuffer 的区别
JAVA 平台提供了两个类: String 和 StringBuffer, 它们可以储存和操作字符串, 即包含多个字符的字符数据. 这个 String 类提供了数值不可改变的字符串. 而这个 StringBuffer 类提供的字符串进行修改.
String 覆盖了 equals 方法和 hashCode 方法, 而 StringBuffer 没有覆盖 equals 方法和 hashCode 方法, 所以, 将 StringBuffer 对象存储进 Java 集合类中时会出现问题.
31, 数组有没有 length()这个方法? String 有没有 length()这个方法?
数组没有 length()这个方法, 有 length 的属性. String 有有 length()这个方法.
32,final, finally, finalize 的区别.
final 用于声明属性, 方法和类, 分别表示属性不可变, 方法不可覆盖, 类不可继承.
finally 是异常处理语句结构的一部分, 表示总是执行.
finalize 是 Object 类的一个方法, 在垃圾收集器执行的时候会调用被回收对象的此方法, 可以覆盖此方法提供垃圾收集时的其他资源回收.
33, 运行时异常与一般异常有何异同?
异常表示程序运行过程中可能出现的非正常状态, 运行时异常表示虚拟机的通常操作中可能遇到的异常, 是一种常见运行错误. java 编译器要求方法必须声明抛出可能发生的非运行时异常, 但是并不要求必须声明抛出未被捕获的运行时异常.
34,error 和 exception 有什么区别?
error 表示恢复不是不可能但很困难的情况下的一种严重问题. 比如说内存溢出. 不可能指望程序能处理这样的情况. exception 表示一种设计或实现问题. 也就是说, 它表示如果程序运行正常, 从不会发生的情况.
35, 请写出你最常见到的 5 个 runtime exception.
ClassCastException 类转换异常, IllegalArgumentException 非法参数异常, IndexOutOfBoundsException 数组越界异常, NullPointerException 空指针异常, ArrayStoreException 数据存储异常.
36,sleep() 和 wait() 有什么区别?
sleep 就是正在执行的线程主动让出 CPU,CPU 去执行其他线程, 在 sleep 指定的时间过后, CPU 才会回到这个线程上继续往下执行, 如果当前线程进入了同步锁, sleep 方法并不会释放锁, 即使当前线程使用 sleep 方法让出了 CPU, 但其他被同步锁挡住了的线程也无法得到执行. wait 是指在一个已经进入了同步锁的线程内, 让自己暂时让出同步锁, 以便其他正在等待此锁的线程可以得到同步锁并运行, 只有其他线程调用了 notify 方法(notify 并不释放锁, 只是告诉调用过 wait 方法的线程可以去参与获得锁的竞争了, 但不是马上得到锁, 因为锁还在别人手里, 别人还没释放. 如果 notify 方法后面的代码还有很多, 需要这些代码执行完后才会释放锁, 可以在 notfiy 方法后增加一个等待和一些代码, 看看效果), 调用 wait 方法的线程就会解除 wait 状态和程序可以再次得到锁后继续向下运行.
37, 同步和异步有何异同, 在什么情况下分别使用他们? 举例说明.
如果数据将在线程间共享. 例如正在写的数据以后可能被另一个线程读到, 或者正在读的数据可能已经被另一个线程写过了, 那么这些数据就是共享数据, 必须进行同步存取.
当应用程序在对象上调用了一个需要花费很长时间来执行的方法, 并且不希望让程序等待方法的返回时, 就应该使用异步编程, 在很多情况下采用异步途径往往更有效率.
38, 多线程有几种实现方法? 同步有几种实现方法?
多线程有两种实现方法, 分别是继承 Thread 类与实现 Runnable 接口
同步的实现方面有两种, 分别是 synchronized,wait 与 notify
wait(): 使一个线程处于等待状态, 并且释放所持有的对象的 lock.
sleep(): 使一个正在运行的线程处于睡眠状态, 是一个静态方法, 调用此方法要捕捉 InterruptedException 异常.
notify(): 唤醒一个处于等待状态的线程, 注意的是在调用此方法的时候, 并不能确切的唤醒某一个等待状态的线程, 而是由 JVM 确定唤醒哪个线程, 而且不是按优先级.
Allnotity(): 唤醒所有处入等待状态的线程, 注意并不是给所有唤醒线程一个对象的锁, 而是让它们竞争.
39, 启动一个线程是用 run()还是 start()?
启动一个线程是调用 start()方法, 使线程就绪状态, 以后可以被调度为运行状态, 一个线程必须关联一些具体的执行代码, run()方法是该线程所关联的执行代码.
40, 当一个线程进入一个对象的一个 synchronized 方法后, 其它线程是否可进入此对象的其它方法?
分几种情况:
1. 其他方法前是否加了 synchronized 关键字, 如果没加, 则能.
2. 如果这个方法内部调用了 wait, 则可以进入其他 synchronized 方法.
3. 如果其他个方法都加了 synchronized 关键字, 并且内部没有调用 wait, 则不能.
4. 如果其他方法是 static, 它用的同步锁是当前类的字节码, 与非静态的方法不能同步, 因为非静态的方法用的是 this.
41, 线程的基本概念, 线程的基本状态
一个程序中可以有多条执行线索同时执行, 一个线程就是程序中的一条执行线索, 每个线程上都关联有要执行的代码.
状态: 就绪, 运行, synchronize 阻塞, wait 和 sleep 挂起, 结束. wait 必须在 synchronized 内部调用.
42, 简述 synchronized 和 java.util.concurrent.locks.Lock 的异同?
主要相同点: Lock 能完成 synchronized 所实现的所有功能
主要不同点: Lock 有比 synchronized 更精确的线程语义和更好的性能.
synchronized 会自动释放锁, 而 Lock 一定要求程序员手工释放, 并且必须在 finally 从句中释放.
43, 介绍 Collection 框架的结构
答: 参考 https://www.cnblogs.com/bingyimeiling/p/10255037.html
44,Collection 框架中实现比较要实现什么接口
comparable/comparator
45,ArrayList 和 Vector 的区别
(1)同步性:
Vector 是线程安全的, 也就是说是它的方法之间是线程同步的, 而 ArrayList 是线程序不安全的, 它的方法之间是线程不同步的. 如果只有一个线程会访问到集合, 那最好是使用 ArrayList, 因为它不考虑线程安全, 效率会高些; 如果有多个线程会访问到集合, 那最好是使用 Vector, 因为不需要我们自己再去考虑和编写线程安全的代码.
(2)数据增长:
ArrayList 与 Vector 都有一个初始的容量大小, 当存储进它们里面的元素的个数超过了容量时, 就需要增加 ArrayList 与 Vector 的存储空间, 每次要增加存储空间时, 不是只增加一个存储单元, 而是增加多个存储单元, 每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡. Vector 默认增长为原来两倍, 而 ArrayList 的增长策略在文档中没有明确规定(从源代码看到的是增长为原来的 1.5 倍).ArrayList 与 Vector 都可以设置初始的空间大小, Vector 还可以设置增长的空间大小, 而 ArrayList 没有提供设置增长空间的方法.
总结: 即 Vector 增长原来的一倍, ArrayList 增加原来的 0.5 倍.
46,HashMap 和 Hashtable 的区别
一. 历史原因: Hashtable 是基于陈旧的 Dictionary 类的, HashMap 是 Java 1.2 引进的 Map 接口的一个实现二. 同步性: Hashtable 是线程安全的, 也就是说是同步的, 而 HashMap 是线程序不安全的, 不是同步的三. 值: 只有 HashMap 可以让你将空值作为一个表的条目的 key 或 value
47,List 和 Map 区别?
一个是存储单列数据的集合, 另一个是存储键和值这样的双列数据的集合, List 中存储的数据是有顺序, 并且允许重复; Map 中存储的数据是没有顺序的, 其键是不能重复的, 它的值是可以有重复的.
48,List, Set, Map 是否继承自 Collection 接口?
List,Set 是, Map 不是
49, 说出 ArrayList,Vector, LinkedList 的存储性能和特性
ArrayList 和 Vector 都是使用数组方式存储数据, 此数组元素数大于实际存储的数据以便增加和插入元素, 它们都允许直接按序号索引元素, 但是插入元素要涉及数组元素移动等内存操作, 所以索引数据快而插入数据慢, Vector 由于使用了 synchronized 方法(线程安全), 通常性能上较 ArrayList 差, 而 LinkedList 使用双向链表实现存储, 按序号索引数据需要进行前向或后向遍历, 但是插入数据时只需要记录本项的前后项即可, 所以插入速度较快.
LinkedList 也是线程不安全的, LinkedList 提供了一些方法, 使得 LinkedList 可以被当作堆栈和队列来使用.
50,Collection 和 Collections 的区别.
Collection 是集合类的上级接口, 继承与他的接口主要有 Set 和 List.
Collections 是针对集合类的一个帮助类, 他提供一系列静态方法实现对各种集合的搜索, 排序, 线程安全化等操作.
51, 说出一些常用的类, 包, 接口, 请各举 5 个
常用的类: Date,System,List,HashMap,String , Integer
常用的包: java.lang ,java.io, java.util, java.sql,javax.servlet
常用的接口: List, Map ,Document,NodeList ,Servlet,HttpServletRequest,HttpServletResponse
52,java 中有几种类型的流? JDK 为每种类型的流提供了一些抽象类以供继承, 请说出他们分别是哪些类?
字节流, 字符流. 字节流继承于 InputStream OutputStream, 字符流继承于 InputStreamReader OutputStreamWriter.
53, 什么是 java 序列化, 如何实现 java 序列化? 或者请解释 Serializable 接口的作用.
我们有时候将一个 java 对象变成字节流的形式传出去或者从一个字节流中恢复成一个 java 对象, 例如, 要将 java 对象存储到硬盘或者传送给网络上的其他计算机, 这个过程我们可以自己写代码去把一个 java 对象变成某个格式的字节流再传输, 但是, jre 本身就提供了这种支持, 我们可以调用 OutputStream 的 writeObject 方法来做, 如果要让 java 帮我们做, 要被传输的对象必须实现 serializable 接口, 这样, javac 编译时就会进行特殊处理, 编译的类才可以被 writeObject 方法操作, 这就是所谓的序列化. 需要被序列化的类必须实现 Serializable 接口, 该接口是一个 mini 接口, 其中没有需要实现的方法, implements Serializable 只是为了标注该对象是可被序列化的.
54,heap 和 stack 有什么区别.
java 的内存分为两类, 一类是栈内存, 一类是堆内存. 栈内存是指程序进入一个方法时, 会为这个方法单独分配一块私属存储空间, 用于存储这个方法内部的局部变量, 当这个方法结束时, 分配给这个方法的栈会释放, 这个栈中的变量也将随之释放.
堆是与栈作用不同的内存, 一般用于存放不放在当前方法栈中的那些数据, 例如, 使用 new 创建的对象都放在堆里, 所以, 它不会随方法的结束而消失. 方法中的局部变量使用 final 修饰后, 放在堆中, 而不是栈中.
55,GC 是什么? 为什么要有 GC?
GC 是垃圾收集的意思(Gabage Collection), 内存处理是编程人员容易出现问题的地方, 忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃, Java 提供的 GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的, Java 语言没有提供释放已分配内存的显示操作方法.
56, 世界 500 强面试题(百度网盘下载)
链接: https://pan.baidu.com/s/1onurVWdXCbh6VCBsYO1Teg
来源: https://www.cnblogs.com/bingyimeiling/p/10294498.html