Java开发面试题及答案今天抽空整理一下Java开发面试中的那些事,帮助正在找工作的你求职还是想换工作找工作的兄弟姐妹们!分享当前Java开发常见面试题及题型答案,供大家阅读参考。Java基础学习资料点击下方!!!完整的Java学习资料1、String类可以继承吗?String类是用final关键字声明的,不能继承被final关键字修饰的类。接下来我们可以看一下String类的源码片段:publicfinalclassStringimplementsjava.io.Serializable,Comparable,CharSequence{/**该值用于字符存储。*/私有最终字符值[];/**缓存字符串的哈希码*/privateinthash;//默认为0/**使用JDK1.0.2的serialVersionUID实现互操作性*/privatestaticfinallongserialVersionUID=-6849794470754667710L;开发人员,将String类定义为final?因为字符串池只有在字符串不可变的情况下才有可能。字符串池的实现可以在运行时节省大量的堆空间,因为不同的字符串变量都指向池中的同一个字符串。但是如果字符串是可变的,那么Stringinterning就不会实现,因为在这种情况下,如果变量改变了它的值,指向这个值的其他变量的值也会一起改变。如果字符串是可变的,则会导致严重的安全问题。例如,以字符串形式传入数据库的用户名和密码,以获取与数据库的连接,或者在socket编程中,以字符串形式传入主机名和端口。因为字符串是不可变的,它的值是不能改变的,否则黑客就可以利用漏洞,改变字符串指向的对象的值,造成安全漏洞。因为字符串是不可变的,所以是多线程安全的,同一个字符串实例可以被多个线程共享。这消除了由于线程安全问题而需要使用同步。字符串本身是线程安全的。因为字符串是不可变的,HashCode在创建的时候就缓存起来了,不需要重新计算。这使得字符串非常适合作为Maps中的键,并且字符串的处理速度比其他键对象更快。这就是为什么HashMap中的键经常使用字符串。●除了修饰类,final关键字还有哪些用途?final修饰的变量,一旦赋值,就不能再赋值;final修改的方法不能被覆盖;final修饰的实例变量必须手动赋值,不能使用系统默认值;final修饰的实例变量一般与static结合使用来声明一个常量;注意:final不能与abstract关键字一起使用。简而言之,final意味着最终的和不可变的。2、&和&&有什么区别?●&运算符是:逻辑与;&&运算符是:短路与。●程序中&和&&最后的运行结果是完全一样的,只是&&有短路现象。当&&运算符左边的表达式结果为false时,右边的表达式不执行,此时发生短路。现象。如果是&运算符,不管左边的表达式是真还是假,右边的表达式都会被执行。这是两者的本质区别。●当然,&运算符也可以用在二元运算中,比如按位与运算。3.两个具有相同值的对象的equals结果为真,但是它们可以有不同的hashCode。这句话对吗?不是,如果两个对象x和y满足x.equals(y)==true,它们的哈希值(hashCode)应该相同。Java对equals方法和hashCode方法的规定如下:(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值必须相同;(2)如果两个对象的hashCode相同,则不必相同。当然你也可以不按要求去做,但是如果你违反了上面的原则,你会发现在使用集合的时候,Set集合中会出现同一个对象,添加新元素的效率会大大降低(对于哈希存储系统,如果哈希码频繁碰撞,访问性能会急剧下降)。许多Java程序员都知道equals和hashCode方法,但很多人只是了解它。在JoshuaBloch的名著《Effective Java》(《Effective Java》在很多公司,是Java程序员的必读书籍,如果你还没有读过,那就赶快去买一本)是这样介绍equals方法的:首先,equals方法必须满足自反性(x.equals(x)必须返回true),对称性(x.equals(y)返回true,y.equals(x)也必须返回true),传递性(x.equals(z)必须在x.equals(y)和y.equals(z)都返回true时返回true),以及一致性(当x和y引用的对象信息没有被修改时,多次调用x.equals(y)应该得到相同的返回值),并且对于任何非空值引用x,x.equals(null)必须返回false。实现高质量equals方法的技巧包括:使用==运算符检查“参数是否是对该对象的引用”;使用instanceof运算符检查“参数的类型是否正确”;输入对象的属性是否匹配;写完equals方法,问问自己是否满足对称性、传递性、一致性;重写equals时总是重写hashCode;不要将equals方法参数中的Object对象替换成其他类型,重写时不要忘记@Override注解。4、在Java中,如何跳出当前的多重嵌套循环?在最外层循环前加上outfor等标记,然后使用breakoutfor;跳出多个循环。例如下面的代码:publicclassTestBreak{publicstaticvoidmain(String[]args){outfor:for(inti=0;i<10;i++){for(intj=0;j<10;j++){如果(j==5){breakoutfor;}System.out.println("j="+j);}}}}运行结果如下:j=0j=1j=2j=3j=45,重载(overload)和重写(override)的区别?重载方法可以通过返回类型来区分吗?方法重载和重写都是实现多态的方法。不同的是前者实现了编译时多态,后者实现了运行时多态。重载发生在一个类中,具有相同名称的方法如果具有不同的参数列表(不同的类型、数量和顺序),则被认为是重载。重写发生在子类和父类之间。重写要求子类重写的方法与父类重写的方法具有相同的返回类型,比父类重写的方法更易访问,不能与父类重写的方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊要求。●方法重载规则:方法名相同,但参数列表中参数的顺序、类型和个数不同。重载与方法的返回值无关,它存在于父类和子类中,存在于同一个类中。可以抛出不同的异常,可以使用不同的修饰符。●方法重写规则:参数列表、方法名、返回值类型必须完全一致;构造方法不能被覆盖;声明为final的方法不能被覆盖;声明为静态的方法不能被覆盖(覆盖和多态联合是有意义的);访问权限不能低于父类;重写的方法不能抛出更广泛的异常;6.当一个对象作为参数传递给一个方法时,这个方法可以改变对象的属性,并且可以返回改变后的结果,那么这里是值传递还是引用传递?这就是价值转移。Java语言中的方法调用只支持参数的值传递。当对象实例作为参数传递给方法时,参数的值是对象的内存地址。这个值(内存地址)传过去后,同一个内存地址指向堆内存中的同一个对象,所以不管用哪个引用来操作这个对象,对象的属性都会发生变化。7.为什么方法不能根据返回类型区分重载?我们看下面的代码:publicvoidtestMethod(){doSome();}publicvoiddoSome(){}publicintdoSome(){return1;}在Java语言中,调用一个方法即使方法有returnvalue,我们也可以收不到这个返回值。比如上面两个方法doSome()在testMethod()中调用时,Java编译器无法区分调用的是哪个方法。所以对于编译器来说,doSome()方法不是重载而是重复,编译器报错。所以这两个方法的区分不能依赖于方法的返回值类型。8、抽象类(abstractclass)和接口(interface)有什么异同?区别:●构造函数可以定义在抽象类中,不能定义在接口中。●抽象类可以有抽象方法和具体方法,接口不能有具体方法;●接口中的所有成员都是public,抽象类中的成员可以使用private、public、protected、default等;●抽象类中可以定义成员变量,接口中只能定义常量;●有抽象方法的类必须声明为抽象类,抽象类不一定有抽象方法;●抽象类接口中可以包含静态方法,接口中不能包含静态方法;●一个类只能继承一个抽象类,一个类可以实现多个接口;相同点:●不能实例化;●抽象类和接口类型可以作为引用类型;●如果一个类继承了某个抽象类或者实现了某个接口,则需要实现其中所有的抽象方法,否则该类仍然需要声明为抽象类;9.char变量可以存储一个汉字,为什么?char类型可以存储一个汉字,因为Java中使用的编码是Unicode(不选择任何特定的编码,直接使用字符集中的字符数,这是统一的唯一方法),一个char类型占用2bytes(16位),所以放一个中文是没有问题的。补充:使用Unicode意味着字符在JVM内外有不同的表示。在JVM内部,它们都是Unicode。当字符从JVM内部传输到外部(比如存入文件系统)时,需要进行编码转换。所以Java中有字节流和字符流,还有在字符流和字节流之间进行转换的转换流,比如InputStreamReader和OutputStreamReader。这两个类是字节流和字符流之间的适配器类。代码转换的任务。10、一个抽象方法可以同时是static的,可以同时是native的,可以同时是synchronized的吗?两者都不是。●抽象方法需要被子类重写,而静态方法不能被重写,所以两者是矛盾的。●native方法是由native代码(如C++代码)实现的方法,而abstract方法没有实现,这是矛盾的。●synchronized与方法的实现细节有关,而抽象方法不涉及实现细节,所以也是矛盾的。11.==和equals有什么区别?equals和==最大的区别是,一个是方法,一个是运算符。●==:如果要比较的对象是基本数据类型,则比较的是值是否相等;如果比较的是引用数据类型,那么就是比较对象的地址值是否相等。●equals():用于比较两个对象的内容是否相等。equals方法不能用于基本数据类型的变量。如果不重写equals方法,则比较引用类型变量指向的对象地址。12.解释静态变量和实例变量的区别?无论创建多少个对象,内存中只有一个静态变量;实例变量必须依赖于一个实例,你需要先创建一个对象,然后通过对象访问它。静态变量可以允许多个对象共享内存。13.break和continue有什么区别?●break和continue是用来控制循环的语句。●break用于彻底结束一个循环,跳出循环体执行循环后面的语句。continue用于跳过本次循环,继续下一次循环。14.Strings="你好";s=s+"世界!";这两行代码执行后,原来的String对象中的内容是不是发生了变化?不是。因为String被设计成一个不可变类,所以它的所有对象都是不可变对象。在这段代码中,s原本指向了一个内容为“Hello”的String对象,然后我们对s进行了“+”操作,那么s指向的对象是否发生了变化呢?答案是不。这时候s已经不指向原来的对象了,而是指向了另一个String对象,内容是“Helloworld!”,原来的对象还在内存中,只是引用变量s不再指向它了。通过上面的描述,我们不难得出另一个结论。如果经常对字符串进行各种修改,或者说是不可预见的修改,那么使用String来表示字符串会造成很大的内存开销。因为String对象创建后不能改变,所以需要一个String对象来表示每一个不同的字符串。这时候,你应该考虑使用StringBuffer/StringBuilder类,它允许修改而不是为每个不同的字符串生成一个新的对象。此外,这两个类之间的对象转换非常容易。同时我们也可以知道,如果我们要使用一个内容相同的字符串,就不用每次都创建一个新的String。比如我们要在构造函数中初始化一个名为s的String引用变量,并设置为初始值,应该这样做:s=newString("实力节点,口碑Java黄埔军校");不这样做:s=newString("实力节点,口碑Java黄埔军校");后者每次都会调用构造函数,生成一个新的对象,性能低内存开销大,而且没有意义,因为String对象是不能改变的,所以对于内容相同的字符串,只需要一个String对象来表示即可.也就是说,上面的构造函数被多次调用,创建了多个对象,它们的String类型属性都指向同一个对象。上面的结论也是基于这样一个事实,对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。使用关键字new调用构造函数总是创建一个新对象,无论内容是否相同。至于为什么要把String类设计成不可变类,是由它的用途决定的。事实上,不仅是String,Java标准类库中的很多类都是不可变的。在开发系统的时候,我们有时需要设计不可变类来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点。比如,因为它的对象是只读的,所以不会有多线程并发访问的问题。当然,也有一些缺点。例如,每个不同的状态都需要用一个对象来表示,这可能会导致性能问题。所以Java标准类库也提供了一个可变版本,即StringBuffer。