继续我的复习刷题
接口方法可以使用abstract修饰
问题:
java接口的方法修饰符可以为?(忽略内部接口)
A. private
B. protected
C. final
D. abstract
正确答案: D 你的答案: D (正确)
虽然说接口中的方法都是抽象的,平时不写abstract,但是是可以使用abstract修饰的,例如:
public interface TestInterface {
abstract void method1();
}
这段代码没有任何问题,但Idea会好心提示:Modifier 'abstract' is redundant for interface methods
(即这个修饰符是多余的)
<init>方法是怎么组成的
问题:
在创建派生类对象,构造函数的执行顺序()
A. 基类构造函数,派生类对象成员构造函数,派生类本身的构造函数
B. 派生类本身的构造函数,基类构造函数,对象成员构造函数
C. 基类构造函数,派生类本身的构造函数,派生类对象成员构造函数
D. 对象成员构造函数,基类构造函数,派生类本身的构造函数
正确答案: A 你的答案: C (错误)
这道题我不太理解所谓的对象成员构造函数
是什么,后面想了一下应该是指如果成员字段是一个对象的话,调用的构造函数吧。
那么这其实就涉及<init>
这个方法的知识点了。
<cinit>
这个方法的组成特别好记:就是静态字段赋值和静态代码块从上到下连接构成的。
然而<init>
这个方法呢?
// 成员字段的类别
class ChildrenClass {
public ChildrenClass(){
System.out.println("成员字段的赋值");
}
}
class BaseClass{
public BaseClass(){
System.out.println("父类的构造函数");
}
{
System.out.println("父类的非静态域");
}
}
public class TestConstructor2 extends BaseClass{
public TestConstructor2(){
System.out.println("自身的构造函数");
}
{
System.out.println("自身的非静态域");
}
public ChildrenClass childrenClass = new ChildrenClass();
public static void main(String[] args) {
TestConstructor2 constructor2 = new TestConstructor2();
}
}
先看一下这段代码,输出是什么?
父类的非静态域
父类的构造函数
自身的非静态域
成员字段的赋值
自身的构造函数
再看一下字节码:
---------调用父类的init方法-------------
0 aload_0
1 invokespecial #1 <com/rhett/javafoundation/BaseClass.<init>>
---------非静态域方法------------------
4 getstatic #2 <java/lang/System.out>
7 ldc #3 <自身的非静态域>
9 invokevirtual #4 <java/io/PrintStream.println>
---------成员字段的赋值-----------------
12 aload_0
13 new #5 <com/rhett/javafoundation/ChildrenClass>
16 dup
17 invokespecial #6 <com/rhett/javafoundation/ChildrenClass.<init>>
20 putfield #7 <com/rhett/javafoundation/TestConstructor2.childrenClass>
---------自身的构造函数-----------------
23 getstatic #2 <java/lang/System.out>
26 ldc #8 <自身的构造函数>
28 invokevirtual #4 <java/io/PrintStream.println>
31 return
可以看到,顺序是这样的:
- 调用父类的
方法 - 非静态域方法+成员字段的赋值(经实测,这两个的顺序就是代码中书写的顺序从上到下构成的)
- 自身的构造函数
字符串相加会触发从字符串常量池中取值吗
题目:
有以下代码片段:
String str1="hello";
String str2="he"+ new String("llo");
System.out.println(str1==str2);
请问输出的结果是:
A. true
B. 都不对
C. null
D. false
正确答案: D 你的答案: A (错误)
字符串字面量的机制,我已经在String s = new String("123");创建了几个String对象?中谈过了,然而这道题目我还是选错了,主要是没有认真思考,像这样的字符串加法,是不存在编译时优化的,内部机制还是通过使用StringBuilder去实现的字符串拼接,最终结果和字符串常量池中的对象肯定是不同的。
那什么情况下会出现编译时优化呢?就是修改为下面这段代码:
String str1="hello";
String str2="he"+"llo";
System.out.println(str1==str2);
就会输出为true了。
Java的自动转型规则
题目:
byte b1=1,b2=2,b3,b6,b8;
final byte b4=4,b5=6,b7;
b3=(b1+b2); /*语句1*/
b6=b4+b5; /*语句2*/
b8=(b1+b4); /*语句3*/
b7=(b2+b5); /*语句4*/
System.out.println(b3+b6);
下列代码片段中,存在编译错误的语句是()
A. 语句2
B. 语句1
C. 语句3
D. 语句4
正确答案: B C D 你的答案: D (错误)
这道题涉及一个知识点,我之前确实不知道:(来自牛客网用户:Pandora)
Java表达式转型规则由低到高转换:
1. 所有的byte,short,char型的值将被提升为int型;
2. 如果有一个操作数是long型,计算结果是long型;
3. 如果有一个操作数是float型,计算结果是float型;
4. 如果有一个操作数是double型,计算结果是double型;
5. 被fianl修饰的变量不会自动改变类型,当2个final修饰相操作时,结果会根据左边变量的类型而转化。
第一点这个规则大概是因为没有对应的字节码操作指令,但我确实不知道会自动转为int。
因此:
- 语句1错误:b3=(b1+b2);自动转为int,所以正确写法为b3=(byte)(b1+b2);或者将b3定义为int;
- 语句2正确:b6=b4+b5;b4、b5为final类型,不会自动提升,所以和的类型视左边变量类型而定,即b6可以是任意数值类型;
- 语句3错误:b8=(b1+b4);虽然b4不会自动提升,但b1仍会自动提升,所以结果需要强转,b8=(byte)(b1+b4);
- 语句4错误:b7=(b2+b5); 同上。同时注意b7是final修饰,即只可赋值一次,便不可再改变。
原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/java%e5%9f%ba%e7%a1%80%e6%9f%a5%e7%bc%ba%e8%a1%a5%e6%bc%8f04/