1、Java有没有goto语句
goto是Java中的保留字,在目前版本的Java中没有使用。根据James Gosling(Java之父)编写的《The Java Programming Language》一书的附录中给出了一个Java关键字列表,其中有goto和const,但是这两个是目前无法使用的 关键字,因此有些地方称其为保留字,其实保留字这个词应该有更广泛的意义,因为熟悉C语言的程序员都知道,在系统类库中使用过的有特殊意义的单词或单词的组合都被视为保留字。
2、&和&&的区别
&运算符有两种用法:(1)按位与;(2)逻辑与。
&&运算符是短路与运算。逻辑与和短路与差别是非常巨大的,虽然二者都要求 运算符左右两端的布尔值都是true整个表达式的值才是true。
&&之所以称为短路运算 是因为,如果&&左侧的表达式的值是false,右边的表达式会被直接短路掉,不会进行运算。很多时候我们可能都需要用&&而不是&,例如在验证用户登录时判定用户名不是null并且不是空字符串,应当写为userName!=null&&!userName.equals(""),二者的顺序不能 交换,更不能用&运算符,因为第一个条件如果不成立,根本不能进行字符串的equals比较,否则会产生NullPointException异常。注意:逻辑或运算符“|”和短路或 运算符“||”的差别也是这样。
3、在Java中如何跳出多重嵌套循环
在最外层循环前加一个标记A,然后用break A;可以跳出多重循环。(Java中支持带标签的break和continue语句,作用有点类似于C和C++中的goto语句,但是就像避免要使用goto语句一样,应该避免使用带标签的break和continue,因为它不会让你的程序变得更优雅,很多时候甚至有相反的作用)。
4、两个对象值相同(x.equals(y)== true),但可有不同的hashCode,这句话对不对
不对,如果两个对象x和y 满足x.equals(y)==true,他们的hashCode应当相同。
Java对于 eqauls方法和hashCode方法是这样规定的:(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;(2)如果两个对象的hashCode 相同,它们并不一定相同(hashcode本身就是个函数,是可以重载的,你完全可以写个函数总是返回固定值。但hashcode函数从设计要求上来说,要尽量保证:不同对象的hashcode不同)。如果违背上述原则,就会发现在使用容器是,相同的对象可以出现在Set集合中,同时 增加新元素的效率会大大下降(对于使用Hash存储的系统,如果hashCode频繁冲突将会造成存取性能急剧下降)。
首先equals方法必须满足自反性(x.equals(x)必须返回true)、对称性(x.equals(y)返回true时,y.equals(x)也必须返回true)、传递性(x.equals(y)和y.equals(z)都返回true时,x.equals(z)也必须返回true)和 一致性(当x和y引用的对象信息没有被 )修改时,多次调用x.equals(y)应该得到同样的返回值),而且对于任何非null值的引用x,x.equals(null)必须返回false。
实现高质量的equals方法的诀窍包括:(1)使用==操作符检查“参数是否为这个对象的引用”(2)使用 instanceOf操作符检查“参数是否为正确的类型”(3)对于类中的关键属性,检查 参数传入对象的属性是否与之相匹配(4)编写完equals方法后,问自己它是否满足对称性、传递性、一致性(5)重写equals时总是 要重写hashCode(6)不要将equals方法参数中的Object对象替换为其他的类型,在重写时不要 忘掉@Override注解。
5、是否可以继承String
String是final类,不可以被继承
继承 String本身就是一个错误的行为,对String类型最好的重用方式是关联关系(Has-A)和依赖关系(Use-A)而不是继承关系(Is-A)。
6、当一个对象被当做参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果, 那么这里到底是值传递还是引用传递?
是值传递。Java语言的方法调用只支持参数的值传递。当一个对象实例 作为一个参数 被传递到方法中时,参数的值就是 对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的。C++和C#中可以通过传引用或传输参数来改变传入的参数的值。
7、重载(overload)和重写(override)的 区别? 重载的方法能否根据返回类型进行区分?
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
重载发生在一个类中,同名的方法如果 有不同的参数列表(参数类型不同、参数个数不同 或者两者都不同)则视为重载;
重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明 更多的异常(里氏代换原则)。重载对 返回值类型没有特殊的要求。
方法重载的 规则:
(1)方法名一致,参数列表中 参数的顺序,类型, 个数不同。
(2)重载与方法返回值无关, 存在于父类和子类,同类中
(3)可以抛出不同的异常,可以有不同的修饰符
方法 重写的规则:
(1)参数列表必须完全与被重写方法一致,返回类型必须完全与被重写方法的返回类型一致。
(2)构造方法不能被 重写,声明为final的方法不能被重写,声明为static的方法不能被重写,但是能够被再次声明
(3)访问权限不能比父类中被重写的方法的访问权限更低。
(4)重写的方法能够抛出任何非强制异常(UnchekcedException,也要非运行时异常),无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以
8、为什么函数不能根据返回类型来区分重载?
因为调用时 不能指定类型信息,编辑器不知道你要调用哪个函数。
例如:
float max(int a,int b);
int max(int a,int b);
当调用max(1,2);时无法确定调用的是哪个,单从这一点上来说, 仅返回值类型不同的重载是不应该 允许的。
再比如对下面这两个方法来说,虽然它们有同样的名字和自变量,但其实是很容易区分的:
void f(){}
int f(){}
若编译器可根据上下文(语境)明确 判断出含义,比如在 int x = f()中,那么这样做 完全没有问题。然而,我们也可能调用一个方法,同时忽略返回值;我们通常把这称为“为它的副作用去 调用一个方法”,因为我们 关心得不是 返回值,而是方法调用的 其他效果。所以假如我们像下面这样调用方法:f(); Java怎么样去判断f()的具体调用方式呢?而且别人如何识别并理解代码呢?由于存在这一类问题,所以不能。
函数的返回值只是作为函数运行之后的一个“状态”,他是保持方法的调用者与被调用者进行通信的关键。并不能作为某个方法的“标识”。
9、char类型变量中能不能存储一个中文汉字,为什么?
char 类型可以存储一个中文汉字,因为Java中使用的编码是Unicode(不选择任何特定的编码,直接使用字符在字符集中的编号,这是统一的唯一方法),一个char类型占2个字节(16bit),所以放一个中文没有问题的。
补充:使用Unicode意味字符在JVM内部和外部有不同的表现形式,在JVM内部都是Unicode,当这个字符被从JVM内部 转移到 外部(例如存入文件系统中),需要进行编码转换。所以Java中有字节流和字符流,以及在字符流和字节流之间进行转换的转换流,如InputStreamReader和OutputStreamReader,这两个类是字节流和字符流之间的适配器类,承担了编码转换的任务。
10、抽象类(abstract class)和接口(interface)有什么异同?
不同点:
抽象类:(1)抽象类中可以定义构造器
(2)可以有抽象方法和具体方法
(3)接口中的成员全都是public
(4)抽象类中可以定义成员变量
(5)有抽象方法的类必须声明为抽象类,而抽象类未必要有抽象方法
(6)抽象类中可以包含静态方法
(7)一个类只能继承一个抽象类
接口:(1)接口中不能 定义构造器
(2)方法全部都是抽象方法
(3)抽象 类中的成员可以是private,默认,protected、public
(4)接口中 定义的成员变量实际上都是常量
(5)接口中不能有静态方法
(6)一个类可以实现多个接口
相同点:(1)不能够实例化
(2)可以将抽象类和接口类型作为引用类型
(3)一个类如果继承了某个抽象类或者实现了某个接口都需要 对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类。
11、抽象的(abstract)方法是否可同时是 静态的(static),是否可同时是本地方法(native),是否可 同时被synchronized
都不能。抽象方法需要子类重写,而静态方法是无法被重写的,因此二者是矛盾的。 本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronize和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互 矛盾的。
12、阐述静态变量和实例变量的区别
静态变量:是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象, 一个类不管 创建多少个对象,静态变量在内存中有 且仅有一个拷贝;
实例变量:必须依存于某一实例,需要先 创建对象任何通过对象才能访问到它。静态变量可以实现让多个对象共享内存。
13、== 和equals的区别?
equals和==最大的区别是一个是方法,一个是运算符。
==:如果比较的对象是基本数据类型,则比较的是数值是否相等;如果比较的是引用数据类型,则比较的是对象的地址值是否相等。
equals():用来比较两个对象的内容是否相等。
注意:equals方法不能用于基本数据类型的变量,如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址。
14、break和continue的区别
break和continue都是用来控制循环的语句。
break用于完全结束一个循环,跳出循环体 执行循环后面的语句。
continue用于跳过本次循环,执行下次 循环。
15、String s = "Hello"; s= s+" world";这两行代码执行后,原始的String对象中的内容到底变了没有。
没有。因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。在这段代码中,s原先指向一个String对象,内容是"Hello",然后我们对s进行了“+”操作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向另一个String对象,内容为“Hello world”,原来 那个对象还存在于内存之中,只是s这个引用变量 不再指向它了。
通过上面的说明,我们 很容易导出另一个结论,如果经常对字符串进行各种各样的 修改,或者说,不可预见的修改,那么使用String来代表字符串的话 会引起很大的内存开销。因为String对象建立之后不能再改变,所有对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。并且,这两种类的对象转换十分容易。同时, 我们还可以知道,如果要 使用内容相同的字符串,不必每次都new 一个String。
s="Initial Value"; 而不是 s= new String("Initial Value"); 后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义。因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就是说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。
上面的结论还基于这样一个事实:对于 字符串常量,如果内容 相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递 一组相关的值, 这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java 标准类库还提供了一个可变版本,即StringBuffer。