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