JavaSE基础小知识Ⅱ(很容易错!!!)

发布于:2024-05-12 ⋅ 阅读:(161) ⋅ 点赞:(0)

1. 变量被final修饰后不能再指向其他对象,但可以重写

如果是引用变量被final修饰,那么的确如此;
基本变量不能重写

2. 下列代码的输出结果是?

public class Test {
  static {
	  int x = 5; 
  }
  static int x,y;   

  public static void main(String[] args) {
        x--;   
        myMethod();
        System.out.println(x+y+ ++x);
  }
  
  public static void myMethod() {
	  y = x++ + ++x;
  }
  
}

答案:3
解析:
静态代码块的变量属于局部变量,这里的5,代码块结束就会销毁

  static {
	  int x = 5; 
  }
static int x,y;   // 全局基本类型的变量,默认值0
public static void main(String[] args) {
        x--;   
        myMethod();
        System.out.println(x+y+ ++x);
  }
  
  public static void myMethod() {
	  y = x++ + ++x;
  }

x–变成-1
myMethod方法,x++的自增在两个x之间的+运行之后才会执行,所以y = -1+1 = 0
最后打印的结果1+0+2 = 3

3.下面哪些赋值语句是正确的?

A:long text = 012;
B:float t = -412;
C:int other = (int) true;
D:double d = 0x12345678;
E:byte b = 128;

答案:A,B,D

A正确,因为0开头的数字代表8进制数字,,010转化成是十进制就是8
在这里插入图片描述
B,小一点的int转float不会出错,大int转float会出错,因为float有效位数只有23位,不足以全部容纳32位的int

D,任何int转double不会出错,因为double的有效位数是53位,足够容纳全部的int

4. 下列程序的执行结果?

class Base {
	public Base(String s) {
		System.out.println("B");
	}
}
public class Dervid extends Base {
	public Dervid(String s) {
		System.out.println("D");
	}
	public static void main(String[] args) {
		System.out.println("C");
	}
}

A: BD
B: DB
C: C
D: 编译错误

答案是D
在这里插入图片描述

java当中,我们都知道一个规则,就是子类执行构造方法时,必须执行父类的同样结构的构造方法,这是由于继承的成员复用导致的

前置知识1

继承的成员复用(成员变量和成员方法可以传递给子类使用),由多个对象创建并功能叠加实现的

在这里插入图片描述
A类是父类,B类是A类的子类

我们可以看到,B类的对象当中同时存在了A类的对象+B类的对象,所以子类构造方法的调用必然会静默调用父类的构造方法

前置知识2

当父类和子类都没有重载构造方法的时候,java会默认使用super()关键字实现前置知识1里面的机制

public class A {
}

public class B extends A{

    public static void main(String[] args) {
        B b = new B();
    }
}

java帮我们自动实现了无参构造

上面的代码其实隐含了一些代码执行

public class A {
	public A(){
	}
}
public class B extends A{

    public static void main(String[] args) {
        B b = new B();
    }
	
	// java帮我们自动创建无参构造,只有在无参构造当中才会自动追加一个super()执行父类的无参构造
	public B(){
		super();
	}
}

但是我们一旦给父类创建了有参构造,去代替无参构造,子类的构造方法不会自动追加super(),此时子类的所有构造方法都需要程序员手动执行super(父类有参构造参数),也就是说此时子类不可能再有无参构造

public class A {

    public Integer i;

    public A(Integer i) {
        this.i = i;
    }
}
public class B extends A {

    public String t;
	
	// 父类成员变量形参+子类成员变量形参
    public B(Integer i, String t) {
        super(i);
        this.t = t;
    }
	
	// 至少得包含父类的Integer变量作为构造形参
    public B(Integer i) {
        super(i);
    }

    public static void main(String[] args) {
        B b = new B(1);

    }
}

现在我们回到题目
在这里插入图片描述

显然Dervid类作为子类,至少得包含父类的String s成员变量,并且需要显式的调用super(s);

在这里插入图片描述

这样才不会报错

如果此时父类追加一个无参构造

public class A {

    public Integer i;

    public A(Integer i) {
        this.i = i;
    }

    public A() {

    }
}

这样B类就可以有无参构造了

在这里插入图片描述

5.关于final关键字下列说法正确的是

A:如果修饰局部变量必须初始化
B:如果修饰类,则该类只能被一个子类继承
C:如果修饰方法,则该方法不能在子类当中重写
D:如果修饰方法,则该方法所在的类不能被继承

答案:C

final修饰局部变量不需要初始化,只需要在用到这个变量之前初始化即可,因为局部变量的使用范围仅在代码块内部,外部无法访问;
在这里插入图片描述

但是修饰成员变量必须直接初始化/构造方法间接初始化,因为这是全局变量,所有的代码都能访问到它,为了防止值被修改,在创建时就要赋值

在这里插入图片描述
或者构造方法初始化

在这里插入图片描述
如果这个全局变量是static的,那么只有直接初始化一条路可以走
在这里插入图片描述
在这里插入图片描述
因为static变量无法在非静态的方法中使用,构造方法全都是非静态的

此时有人会问,那static+final修饰的局部变量呢?

不好意思,static不能修饰局部变量

在这里插入图片描述
因为static是类共享的,局部变量不可能类共享,两者冲突

6. 下列代码运行的结果是

public class DemoTest {
	public static void main(String[] args) {
		String s;
		System.out.println("hello" + s);
	}
}

A:在控制台打印hello
B:报异常java.lang.NullPointException
C:编译报错
D:报异常java.RuntimeException

答案:C

很多人会说,因为这里s对象是null,其实不是的
在这里插入图片描述
s对象是null是不会编译错误的

真正错误的原因是s对象没有初始化,甚至连null都不是
在这里插入图片描述
如果初始化赋值null,就不会报错

局部变量不会自动初始化,但是全局的成员变量可以自动初始化为null

在这里插入图片描述