【Java】基础面试题
标签:【每日一题】
到目前为止,整理了Android四大组件、Android基本常识、还有这个Java基础面试题,准备先到这里,
起初目的是为了每天过一眼面试题,有个印象,也不至于不用的东西全忘了,后面找工作需要时也方便,
但其实,面对面试题,更重要的还是对问题本身的理解与掌握,死记硬背是下下策
所以,以后会更有针对性的学习记录知识点
71. String,Stringbuffer,Stringbuilder的区别【2018.4.18】
String 的长度是不可变的;
StringBuffer的长度是可变的,如果对字符串中的内容经常操作,特别是内容要修改时,则用StringBuffer,如果最后需要String,那么使用StringBuffer的toString()方法转换成String类型的数据;StringBuffer是线程安全的;
StringBuilder是从JDK5开始,为StringBuffer类补充了一个单线程使用的等价类;通常应该优先使用StringBuilder类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。
70. 数组有没有length()方法?String有没有length()方法?【2018.4.17】
数组只有length属性;String有length()方法
69. == 和 equals() 方法在字符串变量比较中的不同
== 比较的是引用,相当于比较两个字符串是不是同一个对象
equals()比较的是字符串的内容
68. Java中的流【2018.4.16】
1、流分类
字节流:InputStream,OutputStream
字符流:Reader,Writer
Reader:读取字符流的抽象类
BufferedReader:将字符存入缓冲区,再读取
LineNumberReader:带行号的字符缓冲输入流
InputStreamReader:转换流,字节流和字符流的桥梁,多在编码的地方使用
FileReader:读取字符文件的便捷类。
Writer:写入字符流的抽象类
BufferedWriter:将字符存入缓冲区,再写入
OutputStreamWriter:转换流,字节流和字符流的桥梁,多在编码的地方使用
FileWriter:写入字符文件的便捷类。
InputStream:字节输入流的所有类的超类
ByteArrayInputStream:含缓冲数组,读取内存中字节数组的数据,未涉及流
FileInputStream:从文件中获取输入字节。媒体文件
BufferedInputStream:带有缓冲区的字节输入流
DataInputStream:数据输入流,读取基本数据类型的数据
ObjectInputStream:用于读取对象的输入流
PipedInputStream:管道流,线程间通信,与PipedOutputStream配合使用
SequenceInputStream:合并流,将多个输入流逻辑串联。
OutputStream:此抽象类是表示输出字节流的所有类的超类
ByteArrayOutputStream:含缓冲数组,将数据写入内存中的字节数组,未涉及流
FileOutStream:文件输出流,将数据写入文件
BufferedOutputStream:带有缓冲区的字节输出流
PrintStream:打印流,作为输出打印
DataOutputStream:数据输出流,写入基本数据类型的数据
ObjectOutputStream:用于写入对象的输出流
PipedOutputStream:管道流,线程间通信,与PipedInputStream配合使用
2、流操作规律:
明确源和目的:
数据源:读取,InputStream和Reader
目的:写入:OutStream和Writer
数据是否是纯文本:
是:字符流,Reader,Writer
否:字节流,InputStream,OutStream
明确数据设备:
源设备:内存、硬盘、键盘
目的设备:内存、硬盘、控制台
是否提高效率:用BufferedXXX
3、转换流:将字节转换为字符,可通过相应的编码表获得
转换流都涉及到字节流和编码表
67. Java中的序列化?【2018.4.13】
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题;序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,实现Serializable只是为了标注该对象是可以被序列化的,然后使用一个输出流(如FileOutputStream)来构造一个ObjectOutStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
66.线程池是什么?【2018.4.12】
当一个程序中创建大量线程,并在任务结束后销毁,会给系统带来过度消耗资源,以及过度切换线程的危险,从而可能导致系统崩溃。为此我们应使用线程池来解决这个问题。
首先创建一些线程,他们的集合称为线程池,当服务器接受到一个客户请求后,就从线程池中取出一个空闲的线程为之服务,服务结束后不关闭该线程,而是将该线程还回到线程池中。在线程池的编程模式下,任务是提交给整个线程池,而不是直接交给某个线程,线程池在拿到任务后,它就在内部查找空闲的线程,把任务交给它。一个线程只能执行一个任务,但是可以同时向一个线程池提交多个任务。
65. 简述synchronized 和 java.util.concurrent.locks.Lock的异同【2018.4.11】
相同点:Lock和synchronized都可以实现线程同步
不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手动释放,并且必须在finally从句中释放
64. 同步和异步有何异同,分别在什么情况下使用?
如果数据将在线程间共享,使用同步编程。例如正在写的数据可能被另一个线程读到,或者正在读的数据可能正在被另一个线程写入,那么这些数据就是共享数据,必须进行同步存取。
当应用程序调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法返回时,则使用异步编程,在很多情况下采用异步途径往往更有效率。
63. 线程同步的方法? 【2018.4.10】
实现同步的方法为使用synchronized关键字,实现方式:
- 同步方法。可以是静态和非静态方法,不可以是抽象和接口方法。当一个线程调用这个对象的同步方法,则这个对象的其他所有同步方法将被锁定,不能调用,但可以调用非同步方法。非静态同步方法锁定的是方法所属的主题对象自身。静态同步方法锁定的是主体类对应的Class类型的对象,所以静态同步方法只跟所属类的其他静态方法相互制约。
- 同步块。锁定一个指定的对象,来对同步块中的代码进行同步
62. 当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
其它线程只能访问该对象的其它非同步方法,同步方法不能进入
61. sleep和yield的区别?
yield方法只是让出分配给自己的CPU时间片,并且会立刻进入Runnable状态参与CPU时间的竞争,若程序中没有其它线程,那么该线程马上就会开始往下执行;sleep会进入Blocked状态,等待时间结束事件的发生,然后进入Runnable状态参与CPU时间的竞争
60. sleep()和wait()的区别?【2018.4.9】
sleep() 方法是线程类(Thread)的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间。
因为sleep() 是static静态的方法,他不能改变对象的机锁,当一个synchronized块中调用了sleep()方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。
wait是object类的方法,对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或是notifyAll)唤醒后,本线程才进入对象锁定池准备获得对象锁进入运行状态
59. 启动一个线程使用run()还是start()?【2018.4.4】
启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。但这并不意味着线程就会立即运行。
58. 为什么要使用多线程编程?
多线程就像是人体一样,一直在并行的做许多工作,例如,人可以同时呼吸,血液循环,消化食物等。多线程可以将一个程序划分成多个任务,他们彼此独立的工作,以方便有效的使用处理器和用户的时间
57. 请说明什么是线程安全?【2018.4.3】
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码;如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
线程安全问题都是有全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读取操作,而无写操作,一般来说这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
56. Set集合不能存放相同的元素,使用什么方法区分重复与否?
Set里的元素事不能重复的,使用equals方法和hashCode方法来区分重复与否。覆盖equals方法、hashCode方法用来判断两个对象是否为同一对象
55. ArrayList,Vector,LinkedList的存储性能和特性?【2018.4.2】
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数据元素移动等内存操作,所以索引数据快,插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上比ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快
54. List底层是怎么实现的?双向链表和数组的区别?
在Java中List是一个接口,继承于Collection接口,并定义了添加、删除、取出元素等对集合操作的抽象方法。
双向链表和数组区别为:
- 数组必须事先定义固定的长度(元素的个数),不能适应数据动态的增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费;数组可以根据下标直接存取。
- 链表动态的进行存储分配,可以适应数据动态的增减情况,且可以方便的插入、删除数据项,而数组中插入、删除数据项时,需要移动其它数据项,非常繁琐。
53. List,Set,Map是否继承自Collection接口?【2018.3.30】
List,Set继承自Collection接口,而Map没有继承自Collection接口
52. Vector和ArrayList有什么差异?
- 同步性:Vector是线程安全的(同步),而ArrayList是线程不安全的
- 扩容:当需要扩容时,Vector默认增长一倍,而ArrayList却是一半
51. HashMap和HashSet有什么关系?【2018.3.29】
HashSet底层采用HashMap实现的,请看如下代码:
private transient HashMap<E,Object> map;
上述代码是HashSet类里面定义的一个私有的 成员变量。放进HashSet中对象,其实使用这个HashMap的key来存储的。当调用HashSet的add方法时,实际上是向HashMap中增加了一行(key-value对),该行的key就是向HashSet增加的那个对象,该行的value就是一个Object类型的常量
50. 简述HashTable原理,并说明它和HashMap区别【2018.3.28】
HashTable原理:
HashTable是基于哈希表的实现。通过使用put(Object key,Object value)方法把两个对象进行关联,需要时用get(Object key)取得与key关联的值对象。还可以查询某个对象的索引值等。这里的get方法查找一个对象时与Vector中的get方法再内部实现时有很大不同,在一个Hashtable中查找一个键对象要比在一个Vector中快的多。这是因为Hashtable使用了一种哈希表的技术,在java每个对象缺省都有一个通过Object的hashCode()方法获得的哈希码,Hashtable就是利用这个哈希实现快速查找键对象的。
二者都实现了Map接口,是将唯一键映射到特定的值上,主要区别是:
- HashMap没有排序,允许一个null键和多个null值,而Hashtable不允许
- HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey,因为contains方法容易引起误解
- Hashtable继承自Dictionary类,HashMap是java1.2引进的Map接口的实现
- Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap就必须为之提供外同步。Hashtable和HashMap采用hash、rehash算法大致一样,所以性能不会有很大的差异。
49. HashMap是如何设计的?是如何解决冲突的?【2018.3.27】
- HashMap是基于哈希表的Map接口的非同步实现。在Java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际是一个“链表的数组”的数据结构,每个元素存放链表头结点的数组,即数组和链表的街个体。HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。Entry就是数组中的元素,每个Map.Entry其实就是一个key-value对,它持有一个指向下一个元素的引用,就构成了链表
- HashMap的存储。当我们往HashMap中put元素的时候,先根据Key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。
- HashMap的读取。从HashMap中get元素时,首先计算key的HashCode,找到数组中对应位置的某一元素,然后通过key的equals方法在对应位置的链表中找到需要的元素
- HashMap的resize(rehash)。当HashMap中的元素越来越多的时候,hash冲突的几率也就越来越高,因为数组的长度是固定的。所以为了提高查询的效率,就要对HashMap的数组进行扩容,数组扩容这个操作也会出现在ArrayList中,这是一个常用的操作,而在HashMap数组扩容之后,最消耗性能的点就出现了:原数组中的数据必须重新计算其在新数组中的位置,并放进去,这就是resize。那么HashMap什么时候进行扩容呢?当HashMap中的元素个数超过数组大小loadFactor时,就会进行数组扩容,loadFactor的默认值为0.75,这是一个折中的取值。也就是说,默认情况下,数组大小为16,那么当HashMap中元素个数超过160.75=12的时候,就把数组的大小扩展为2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,扩容是需要进行数组复制的,复制数组是非常消耗性能的操作,所以如果我们已经预知HashMap中元素的个数,那么预设元素的个数能够有效的提高HashMap的性能。
48. Collection 和 Collections的区别?【2018.3.26】
Collection是Java.util 下的接口,它是各种集合的父接口,继承于它的接口主要有Set 和 List;
Collections是个java.util 下的类,是针对集合的帮助类,提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作
47. 集合关系图
集合关系图.png46. final,finally,finalize的区别【2018.3.23】
final 是一个修饰符,表示不可变。如果一个类被声明为final,则它不能再派生出新类,不能作为父类被继承,所以一个类不能既是abstract的又是final的;被声明为final的变量必须在声明时给定初始值,而以后的引用中只能读取,不可修改;被声明为final的方法同样只能使用,不能重载
finalize 是方法名。java技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用。它是在Object类中定义的,因此所有的类都继承了它。子类覆盖finalize()方法以整理系统资源或者执行其他清理工作
finally 异常处理。用在异常处理时提供finally块来执行任何清除操作;如果抛出一个异常,那么相匹配catch子句就会执行,然后控制就会进入finally块(如果有的话),在return前执行。
45. try{}里有个return语句,那么最后的finally{}里的代码会不会执行,何时执行? 【2018.3.22】
会执行,在try里的return前执行
44. java中的异常处理机制的简单原理
当Java程序违反了java的语义规则时,java虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况,一种是java类库内置的语义检查,例如:角标越界,会引发IndexOutOfBoundsException;另一种情况是java允许程序员扩展这种语义检查,程序员可以创建自己的异常,并自由选择在何时用throw关键字引发异常
43. 异常(Exception)分几种类型?有什么区别?写出几个常见异常【2018.3.21】
分类:
运行时异常、非运行时异常。
区别:
- 运行时异常(RuntimeException)又称为非检查异常(Unchecked Exception), 非运行时异常指的是检查异常(Checked Exception)。
- 运行时异常直接或间接的继承RuntimeException的异常。非运行时异常是除了运行时异常以外的其他异常。
- 运行时异常不需要捕获,非运行时异常需要通过try-catch或throws进行处理
常见异常:
- RuntimeException
- NullPointerException:空指针异常,操作空引用时引发
- ClassCastException:类型转换异常,强制类型转换不匹配时引发
- ArrayIndexOutOfBoundsException:角标越界异常,使用一个不存在的数组下标时引发
- 非RuntimeException
- SQLException:提供关于数据库访问出错的异常
- IOException:当发生某种I/O异常时,抛出此异常
- ClassNotFoundException:当应用试图使用Class类中的forName方法、loadClass方法时,抛出该异常
42. 在java中如何引发异常?如何处理?
在java中,可以通过throw关键字来引发异常。
处理异常:
- 使用try-catch捕获异常
- 使用throws抛出异常
41. Checked Exception 和 Unchecked Exception是什么以及他们的区别?【2018.3.20】
首先,java的异常分为Error和Exception。这两类都是接口Throwable的子类。Error及Exception及其子类之间的关系,大致可以用下图简述。
注意事项:
1。 Error仅在java的虚拟机中发生,用户无需在程序中捕捉或者抛出Error。
2。 Exception分为一般的Exception和RuntimeException两类。这里有点让人觉得别扭的是RuntimeException(Unchecked)继承于Exception(Checked)的父类。
PS: checked与unchecked的概念理解:
checked: 一般是指程序不能直接控制的外界情况,是指在编译的时候就需要检查的一类exception,用户程序中必须采用try catch机制处理或者通过throws交由调用者来处理。这类异常,主要指除了Error以及RuntimeException及其子类之外的异常。
unchecked:是指那些不需要在编译的时候就要处理的一类异常。在java体系里,所有的Error以及RuntimeException及其子类都是unchecked异常。再形象直白的理解为不需要try catch等机制处理的异常,可以认为是unchecked的异常。
checked与unchecked在throwable的继承关系中体现为下图:
+-----------+
| Throwable |
+-----------+
/ \
/ \
+-------+ +-----------+
| Error | | Exception |
+-------+ +-----------+
/ | \ / | \ \
\________/ \______/ \
+------------------+
unchecked checked | RuntimeException |
+------------------+
/ | | \
\_________________/
unchecked
40. 内部类可以引用它的包含类的成员吗?有什么限制?【2018.3.19】
如果是静态内部类,只能引用包含类的静态成员。
不是静态内部类,都可以引用。
39. 请解释下面的两个Syatem.out.println输出不同?【2018.3.16】
String s1 = "Hello";
String s2 = "Hello";
System.out.println(s1==s2); // 输出:true
String s3 = new String("Hello");
String s4 = new String("Hello");
System.out.println(s3==s4); // 输出:false
"Hello"是一个字符串常量,它存放在内存的常量池中。在第一行代码执行后创建此对象,而创建s2对象的时候首先会到常量池中检查是否存在字符串“Hello”,如果存在,则直接引用已存在的对象。
s3和s4所应用的对象都是通过new关键字创建的,会在堆中分别创建。这两个引用分别指向不同的两个对象。“==”只有在两个变量引用指向同一个对象时才返回true因此出现如上结果。
38. int 和 Integer 的区别 【2018.3.15】
java语言是一个面向对象的语言,但是java中的基本数据类型却不是面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个基本数据类型对应的类统称为包装类(Wrapper Class)。
java语言提供了两种不同的类型:引用类型和基本数据类型,int是JAVA语言的基本数据类型,Integer是java为int提供的包装类,是引用数据类型。
java中的八个基本数据类型是:byte,short,int,long,float,double,char,boolean
对应的包装类:Byte,Short,Integer,Long,Float,Double,Character,Boolean.
包装类的主要用途:
- 作为和基本数据类型对应的类类型存在,方便涉及到对象的操作
- 包含每种基本数据类型的相关属性如最大值,最小值等,以及相关的操作方法。
37. heap 和 stack 的区别【2018.3.14】
栈(stack)和堆(heap)都是java用来在内存中存放数据的地方,二者区别在于:
- 栈存放基本类型变量和对象引用,当超出作用域后释放;堆存放new出来的对象和数组
- 堆可以动态的分配内存大小,生存期也不必事先告诉编译器,java的垃圾收集器会自动收走这些不再使用的数据。存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈的存取速度比堆要快,仅次于直接位于CPU中的寄存器。堆由于要在运行时动态分配内存,存取速度较慢。
- 栈数据可以共享;堆不可以
- 栈是一种线形集合,其添加和删除元素的操作应在同一段完成,栈按照后进先出方式进行处理;堆地址是不连续的,可随机访问
36. 简述类(class)、类库(class library)、包(package)、jar文件这四个概念间的联系【2018.3.13】
- 类,实际上是对某种类型的对象定义变量和方法的原型。它标识对象是生活中一类具有共同特征的事物的抽象。
- 包,为了更好的组织类,java提供了包机制。包是类的容器,用于分隔类名空间。
- 类库,是用来实现各种功能的类的集合。
- jar,用于发布和使用类库,可 被编译器和jvm直接使用
35. 子类A继承父类B,A a = new A();则父类B构造函数、父类B静态代码块、父类B非静态代码块、以及子类的各个部分执行的先后顺序?
父类B静态代码块--->子类A静态代码块--->父类B非静态代码块--->父类B构造函数--->子类A非静态代码块--->子类A构造函数
34. 接口是否可继承接口?抽象类是否可以实现接口?抽象类是否可继承具体类?【2018.3.12】
相关概念:
接口:接口是一种约束形式,其中只包括成员定义,不包含成员实现的内容。
抽象类:抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。
抽象方法:抽象方法指一些只有方法声明,而没有具体方法体的方法。抽象方法一般存在于抽象或接口中。
答案:
- 接口可以继承接口 extands
- 抽象类可以实现接口
- 抽象类可以继承具体类
- 抽象类中可以有静态的main方法
关于为什么接口不能继承抽象类,我想是因为抽象类可以有方法体,而接口不行,如果继承的话,这一点会冲突
33. 简述垃圾回收的有点和原理。并例举2种回收机制【2018.3.9】
java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存问题迎刃而解,它使得java程序员在编写程序时不在需要考虑内存管理。由于有个垃圾回收机制,java中的对象不再有“作用域”的概念,只有对象的引用才有“作用域”。垃圾回收可以有效的防止内存泄漏,有效的使用可以使用的内存。
垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡或长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。
两种垃圾回收机制如下:
- 增量收集器
增量收集器把堆栈分为多个域,每次仅从一个域回收垃圾。这会造成较小的应用程序中断。 - 分代收集器
这种收集器把堆栈分为两个或多个域,用以存放不同寿命的对象。jvm生成的新对象一般放在其中的某个域中。过一段时间,继续存在的对象将获得使用期并转入更长寿命的域中。分代收集器对不同的域使用不同的算法以优化性能。
32. GC是什么?为什么要有GC?
GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,java提供的GC功能可以自动检测对象是否超过作用域从而达到自动回收内存的目的。java程序员编程的时候不用考虑变量不用时释放内存,java虚拟机可以自动判断出并收集到垃圾。
31. 静态变量和实例变量的区别
静态变量也称为类变量,归全类共有,它不依赖某个对象,可通过类名直接访问,而实例变量必须依存于某一实例,只能通过对象才能访问到它
30. 简述一下static关键字的作用?【2018.3.8】
static表示“静态”的意思,用来修饰成员变量和成员方法,亦可以形成静态代码块。只要这个类被加载,java虚拟机就能根据类名在运行时数据区的方法区内找到它们。因此,static成员可以再它的任何对象创建之前访问,无需引用任何对象。
- 修饰成员变量。用static修饰的成员变量不属于对象的数据结构;static变量是属于类的变量,通常可以通过类名来引用static成员;static成员变量和类的信息一起存储在方法区,而不是在堆中,一个类的static成员变量只有“一份”,无论该类创建了多少对象。
- 修饰成员方法。static修饰的方法则不需要针对某些对象进行操作,其运行结果仅与输入的参数有关,调用时直接用类名引用。由于static在调用时没有具体的对象,因此在static方法中不能对非static成员(对象成员)进行访问。static方法的作用在于提供一些“工具方法”和“工厂方法”等。
- static代码块:属于类的代码块,在类加载期间执行的代码块,只执行一次,可以用来在软件中加载静态资源。
29. String类可否被继承?【2018.3.7】
String类是final类,所以不可被继承。
String的本质是一个char数组,而且被final修饰的字段创建后不可改变
private final char value[];
好处是:
线程安全,字符串常量池数据共享,提高效率,节省内存
28. 构造器Constructor是否可被override?
构造器不能被继承,所以谈不上重写override,但是可以重载overload。
27. 一个subClass怎样调用superclass中的方法(myMethod)和构造方法?【2018.3.6】
子类subclass实例可以直接调用父类superclass未被重写的方法;若子类重写了父类的方法,可以在子类内通过super.方法名()的形式调用父类方法,如:super.myMethod()
创建子类实例时,默认调用父类无参构造方法,若调用父类有参构造方法,可以再子类构造方法中通过super(参数)形式调用
26. abstract class 和 interface有什么区别?【2018.3.5】
从语法角度来说:abstract class方法中可以有自己的数据成员,也可以有非abstract的成员方法,并赋予方法的默认行为,而在interface中一般不定义数据变量,所有方法都是abstract,方法不能拥有默认行为。
从编程角度来说:abstract class在java语言中表示的是一种继承关系,一个类只能使用一次继承关系,而一个类可以实现多个interface。
从问题域角度来书:abstract class在java语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在“is a”关系,即父类和派生类在概念本质上应该是相同的。对于interface来说则不然,并不要求interface的实现者和interface定义在概念本质上一致,仅仅是实现了interface定义的契约而已。
25. java权限修饰符 【2018.3.2】
修饰符/作用域 | 当前类 | 同一package | 子类 | 其它 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | x |
default | √ | √ | x | x |
private | √ | x | x | x |
24. 继承和重载的区别?【2018.3.1】
java的继承是子类对象继承父类对象的成员属性和成员方法,只允许单继承。
在继承的过程中可以实现方法的重写(也称为覆盖),即子类定义一个方法,覆盖从父类那里继承来的同名的方法。每当子类对象调用该方法时都是子类自己定义的方法,只有使用super关键字或父类名为前缀时,才会调用父类原来的方法。方法覆盖是,子类应与父类有完全相同的方法名,返回值类型和参数列表,子类中的覆盖方法不能使用比父类中被覆盖的方法更严格的访问权限。
方法重载要求的是同一个类中,方法名相同,参数列表不同的方法,对返回值没限定
23. 什么时候需要改写hashCode方法?为什么?【2018.2.28】
在改写equals方法的时候总是要改写hashCode方法。如果不这样的话,就会违反Object类的hashCode方法的通用约定,导致这个类无法与所有基于散列值的集合类结合一起正常工作,包括HashMap,HashSet和HashTable。
22. 请分述类及对象的创建模式【2018.2.27】
总共有五种创建模式,分别是单例模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式,其中工厂方法模式为类创建模式,其余四种为对象创建模式。
工厂方法模式(Factory Method,类创建模式):核心工厂类不再负责所有产品的创建,而是将具体创建的工作交个子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
单例模式(Singleton,对象创建模式 ):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
抽象工厂模式(Abstract Factory,对象创建模式):抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。简单说是创建一组相关或相互依赖的复杂对象。
建造模式(Builder,对象创建模式):将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。
原型模式(Prototype,对象创建模式):通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动态的增加或减少产品类,产品类不需要非得有任何事先确定的等级结构,原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。
21. 什么是OOAD?OOAD怎么实现?【2018.2.26】
OOAD(Object Orient Analysis Design,面向对象的分析与设计)是现代软件企业广为采用的一项有效技术。OOAD方法要求在设计中要映射现实世界中指定问题域中的对象和实体,例如:顾客、汽车和销售人员等。这就需要设计要尽可能的接近现实世界,即以最自然的方式表述实体。
使用UML建模语言创建系统的分析模型与设计模型是OOAD实现的主要手段。
20. 排序有哪些方法?【2018.2.24】
- 插入排序(直接插入排序、希尔排序)
- 交换排序(冒泡排序、快速排序)
- 选择排序(直接选择排序、堆排序)
- 归并排序
- 分配排序(箱排序、基数排序)
19. 简单说下什么是递归?什么情况会使用?
- 递归作为一种算法在程序设计语言中广泛应用,是指函数在运行过程中直接或间接调用自身而产生的重入现象
- 递归算法一般用于解决三类问题:
- 数据的定义是按递归定义的(斐波那契函数)
- 问题解法按递归算法实现(回溯)
- 数据的结构形式是按递归定义的(树的遍历,图的搜索)
18. 列出自己常用的jdk包 【2018.2.23】
常用的jdk包如下:
- java.lang:这个包中包含了JDK提供的基础类,如String等都是这里面的,这个包是唯一一个可以不用导入就可以使用的包
- java.io:这个包中包含了与输入输出相关的类,如文件操作等
- java.net:这个包中包含了与网络有关的类,如URL,URLConnection等
- java.util:系统辅助类,特别是集合类Collection,list,map等
- java.sql:数据库操作的类
17. java源文件中是否可以包含多个类,有什么限制?【2018.2.9】
一个java源文件中可以包含多个类,每个源文件中至多有一个public类,如果有的话,那么源文件的名字必须与之相同。如果源文件中没有public类,则源文件用什么名字都可以,但最好还是具有的定的意。一般建议一个源文件中只写一个java类
16. java中会存在内存泄漏吗?简单描述【2018.2.8】
会出现内存泄漏
一般来说内存泄漏有两种情况。一是在堆中分配的内存,在没有将其释放掉的时候,就将所有能访问这块内存的方式都删掉;另一种情况则是在内存对象已经不需要的时候,还仍然保留这这块内存和它的访问方式(引用)。第一种情况,在java中已经由于垃圾回收机制的引入,得到了很好的解决。所以,java中的内存泄漏,主要指的是第二种情况
15. 什么是垃圾回收?什么时候触发垃圾回收?如何降低垃圾回收的触发频率?它能保证程序有足够的可用内存吗? 【2018.2.7】
- 垃圾回收(GC)是Java语言的一个重要特性,作用是释放不在被使用的内存
- 垃圾回收由系统进行管理,在系统认为需要的时候自动启动一个线程进行处理
- 尽量减少垃圾内存,也就是新建对象的数量,可以降低垃圾回收的频率
- 垃圾回收无法保证有足够的内存
14. 什么是进程?
进程是操作系统结构的基础,是一个计算机中正在运行的程序实例。可以分配给处理器并由处理器执行的一个实体,由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元。
13. 你对软件开发中的迭代的理解 【2018.2.6】
软件开发中,各个开发阶段并不是顺序执行,而是每个阶段都在迭代,然后进入下一阶段的开发。这样对于开发中的需求变化,及人员变动都能得到更好的适应。
软件开发过程中迭代模型如下图:
12. 请描述一下java加载class文件的机制
Java中类的加载是由ClassLoader和它的子类实现的,java ClassLoader是一个非常重要的java 运行时组件,它负责运行时查找和装入类文件中的类
11. Java中8种基本数据类型和其所占的字节数?
基本类型 | 大小 | 包装器类型 |
---|---|---|
boolean | - | Boolean |
char | 2 byte | Character |
byte | 1 byte | Byte |
short | 2 byte | Short |
int | 4 byte | Integer |
long | 8 byte | Long |
float | 4 byte | Float |
double | 8 byte | Double |
boolean所占存储空间没有明确指定
10. &和&&的区别? 【2018.2.5】
&和&&都可以执行关系判断。二者的区别是:&运算是把逻辑表达式全部计算完,而&&具有短路计算功能。所谓短路计算,是指系统从左到右进行逻辑表达式的计算,一旦出现计算结果已经确定的情况,则计算过程即被终止。
9. Java中结构化程序设计有哪三种基本流程,分别对应哪些语句?
Java中结构化程序设计有三种基本流程,分别是顺序、选择、循环。
其中,顺序表示程序中的个操作是按照它们出现的先后顺序执行的;选择对应的是if和switch语句;循环对应的是for、do-while和while语句
8. java中的两个关键字:null和void有什么区别?
在java中,void仅用于无返回值的方法上,例如:
public void a(){}
该方法不需要返回数据,故返回值类型设置为void
null则表示对象/变量的值,例如:
String a = null;
表示a没有被实例化,没有只想具体的内存地址
7. 简述TCP/UDP协议的区别?【2018.2.2】
比较项 | TCP | UDP |
---|---|---|
是否可连接 | 面向连接 | 面向非连接 |
传输可靠性 | 可靠的 | 不可靠的 |
应用场合 | 传输大量的数据 | 少量数据 |
速度 | 慢 | 快 |
6. Java跨平台是如何实现的?【2018.2.1】
Java是利用JVM实现跨平台的
Java源代码(*.java)经过java编译器编译成java字节码(*.class),执行java字节码,java字节码经过JVM解释为具体平台的具体指令,并执行。不同平台有不同的JVM,所以Java字节码可以在主流平台上能够解释执行。在这个意义上Java是跨平台的,也就是说:Java的字节码是跨平台的。
5. JVM能有几个实例?
每个java程序对应一个JVM实例,当一个java程序运行时就创建一个JVM实例的个数取决于同时执行的程序个数。
4. JVM、JDK、JRE、JavaSE、JavaME,GC的意思? 【2018.1.31】
JVM:java虚拟机,Java Virtual Machine的缩写。是一个虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机有自己完善的硬体结构,如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM屏蔽了与具体操作系统平台相关信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改的运行。
JDK:java开发工具包,Java development Kit的缩写。JDK是整个Java的核心,包括了Java运行环境、Java工具和Java基础类库。
JRE:Java运行环境,Java Runtime Environment的缩写。运行JAVA程序所必须的环境的集合,包含JVM标准实现及Java核心类库。
JavaSE:Java Standard Edition,标准版,是我们常用的一个版本,从JDK5.0开始,改名为 Java SE,主要用于桌面应用软件的编程。
JavaEE:Java Enterprise Edition,企业版,JavaEE是J2EE的一个新的名称,主要是用于分布式的网络程序的开发。
JavaME:Java Micro Edition,是为机顶盒、移动电话和PDA之类嵌入式消费电子设备提供Java语言平台,包括虚拟机和一系列标准化的Java API。
GC:垃圾回收,Garbage Collection的缩写。当java虚拟机发觉内存资源紧张时,则会自动的去清理无用对象(没有被引用到的对象)所占用的内存空间。
3. Java 中异常分为哪些种类 【2018.1.30】
按 照 异 常 需 要 处 理 的 时 机 分 为 编 译 时 异 常 也 叫 CheckedException 和 运 行 时 异 常 也叫RuntimeException。
只有 java 语言提供了 Checked 异常,Java 认为 Checked 异常都是可以被处理的异常,所以 Java 程序必须显式处理 Checked 异常。如果程序没有处理Checked异常,该程序在编译时就会发生错误无法编译。
这体现了 Java 的设计哲学:没有完善错误处理的代码根本没有机会被执行。对 Checked 异常处理方法有两种:
1 当前方法知道如何处理该异常,则用 try...catch 块来处理该异常。
2 当前方法不知道如何处理,则在定义该方法是声明抛出该异常。
运行时异常只有当代码在运行时才发行的异常,编译时不需要 try catch。Runtime 如除数是 0和数组下标越界等,其产生频繁,处理麻烦,若显示申明或者捕获将会对程序的可读性和运行效率影响很大。所以由系统自动检测并将它们交给缺省的异常处理程序。当然如果你有处理要求也可以显示捕获它们
2. Java中实现多态的机制是什么?
靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。程序调用的方法是在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变
量的类型中定义的方法。
1. 面向对象 【2018.1.29】
面向对象是一种思想,是基于面向过程而言的,是将功能通过对象来实现,将功能封装进对象之中,让对象去实现具体的细节。
面向对象的好处是:
1:将复杂的事情简单化。
2:面向对象将以前的过程中的执行者,变成了指挥者。
3:面向对象这种思想是符合现在人们思考习惯的一种思想。
面向对象的三大特性:
1.封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式
好处:将变化隔离、便于使用、提高复用性、提高安全性
原则:将不需要对外提供的内容隐藏起来;把属性隐藏,提供公共方法对其访问
2.继承:提高代码复用性;继承是多态的前提
注:
①子类中所有的构造函数都会默认访问父类中的空参数的构造函数,默认第一行有super();若无空参数构造函数,子类中需指定;另外,子类构造函数中可自己用this指定自身的其他构造函数。
3.多态:是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象
好处:提高了程序的扩展性
弊端:当父类引用指向子类对象时,虽提高了扩展性,但只能访问父类中具备的方法,不可访问子类中的方法;即访问的局限性。
前提:实现或继承关系;覆写父类方法。