Java基础查缺补漏04

继续我的复习刷题

接口方法可以使用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

可以看到,顺序是这样的:

  1. 调用父类的方法
  2. 非静态域方法+成员字段的赋值(经实测,这两个的顺序就是代码中书写的顺序从上到下构成的)
  3. 自身的构造函数

字符串相加会触发从字符串常量池中取值吗

题目:

有以下代码片段:

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/

(0)
彭晨涛彭晨涛管理者
上一篇 2020年5月28日
下一篇 2020年5月29日

相关推荐

  • Servlet4.0初识总结

    JavaEE8 JavaEE8,是自2013年6月Java企业版的首次更新。JAVAEE8提供了一些新的API,提供了对HTTP/2的新支持。 Servlet4.0 Servlet…

    Java 2019年11月28日
    02030
  • 深入理解java虚拟机第三版读书笔记02

    以下是第二章 Java内存区域与内存溢出异常的内容 运行时数据区域 程序计数器 特点 程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。 程序计数器是…

    2020年1月5日
    0200
  • Java基础查缺补漏05

    继续我的复习刷题 可以有和类名同名的函数 题目: JAVA中,下列语句哪一个正确() A. class中的constructor不可省略B. constructor必须与class…

    Java 2020年5月29日
    0140
  • JUC包下的信号量Semaphore

    概述 信号量,用来限制能同时访问共享资源的线程上限。 public static void main(String[] args) { // 1. 创建 semaphore 对象 …

    Java 2020年2月6日
    0180
  • 为什么说Java只有值传递?

    先说一下。。以后可能不会怎么写Java相关的博客了,因为找到了字节跳动的实习工作,用Go/Python开发后端,所以这几天在抓紧时间学Go,在学Go的时候,了解到Go语言只有值传递…

    Java 2020年6月26日
    03090
  • 深入理解java虚拟机第三版读书笔记05

    续深入理解java虚拟机第三版读书笔记04 HotSpot的算法细节实现 根节点枚举 如何高效的找出所有GC Roots? 迄今为止,所有收集器在根节点枚举这一步骤时都是必须暂停用…

    2020年1月12日
    0550
  • 深入理解java虚拟机第三版读书笔记09

    续深入理解java虚拟机第三版读书笔记08 类加载器 通过一个类的全限定名来获取描述该类的二进制字节流称为类加载器。类加载器可以用户自定义,是java语言流行的一项原因 类与类加载…

    2020年1月23日
    0120
  • Java多线程基础

    多线程应用 异步调用 以调用方角度来讲,如果+ 需要等待结果返回,才能继续运行就是同步+ 不需要等待结果返回,就能继续运行就是异步 同步在多线程中还有另外一个意思,是让多个线程步调…

    2020年1月31日
    0330
  • LinkedList源码分析

    相关文章:ArrayList源码分析 List家族一览: LinkedList简介 LinkedList的超类有List、Queue,说明它既有List的性质也有Queue的性质,…

    2019年12月2日
    070
  • 深入理解java虚拟机第三版读书笔记11

    以下是第十一章 后端编译与优化的内容 把Class文件转换成与本地基础设施(硬件指令集、操作系统)相关的二进制机器码可以视为整个编译过程的后端。 最近几年提前编译也开始兴起,我们在…

    2020年1月27日
    0270

发表回复

登录后才能评论