关于static的一系列面试题目

(1)静态方法中可以使用this/super吗?

不可以,因为静态方法先于对象存在。而this/super表示的是对象。故不可以。

(2)静态方法中可以调用本类的非静态方法吗?

不可以 在本类中调用demo()相当于this.demo,因为静态方法中不可以使用this,所以静态方法不能调用非静态方法

(3)静态方法可以被继承吗? 可以

(4)静态方法可以被重写吗?

不可以 如果父子类中出现了同名的静态方法,称之为隐藏(hide)。

如果父子类中有同名方法,要么都是静态(隐藏),要么都是非静态(重写)

隐藏也遵循"两等两小一大"原则

(5)例题

class A{
	 static String name;
}
public class StaticDemo {
	public static void main(String[] args) {
		A a = new A();
		A a1 = new A();
		a.name = "hello";
		a1.name = "world";
		System.out.println(a.name);
		System.out.println("============");
		System.out.println(a1.name);
	}
}

结果:

world
============
world

分析:static变量是在类加载的时候被加载,而且只被加载一次。被所有实例化该类的对象所共享。

(6)例题

public class StaticDemo2 {
	public static void main(String[] args) {
		new B();
	}
}

class A{
	static{
		System.out.println("Static-A执行了");
	}
	{
		System.out.println("代码块-A执行了");
	}
	public A(){
		System.out.println("构造方法-A执行了");
	}
}

class B extends A{
	static C c = new C();
	static{
		System.out.println("Static-B执行了");
	}
	{
		System.out.println("代码块-B执行了");
	}
	public B(){
		System.out.println("构造方法-B执行了");
	}
}

class C{
	public C(){
		System.out.println("构造方法-C执行了");
	}
}

结果:

Static-A执行了
构造方法-C执行了
Static-B执行了
代码块-A执行了
构造方法-A执行了
代码块-B执行了
构造方法-B执行了

分析:根据static变量、static方法、static代码块先于类对象加载。故实例化之前,先去加载static~。

  1. 实例化B对象
  2. 通过方法区,得知B对象信息,继承A,发现A中含有静态代码块,故先执行A中的Static代码块
  3. 此外,在B对象中有静态变量C,故去执行static C c = new C();然后输出构造方法-C执行了。
  4. 在B对象中还有静态代码块,故在去执行静态代码块中的内容
  5. 然后执行父类A中的构造代码块和构造方法(构造代码块先于构造方法执行)
  6. 最后在执行父类B中的构造代码块和构造方法

补充:如果

static{
        System.out.println("Static-B执行了");
    }

在static C c = new C();上面,则会先打印“Static-B执行了”,在打印C的构造方法中的内容。

(7)例题

public class StaticDemo3 {
	public static void main(String[] args) {
		System.out.println(StaticDemo.i);
	}
}

class StaticDemo{
	static{
		i = 1;
	}
	static int i;
}

结果:1

分析:根据static用法,我们知道static变量是随着类加载到方法区的,而类加载又分为加载-校验-准备-解析-初始化五个步骤。

其中,我们要关注准备阶段和初始化阶段。

  1.  在准备阶段,给i开辟内存空间,并且设定一个标记值
  2. 然后在初始化阶段先执行静态代码块 i = 1代码,舍弃标记值,
  3. 然后再执行静态变量,但是没有赋值操作,所以保留i=1的结果。

(8)例题

public class StaticDemo3 {
	public static void main(String[] args) {
		System.out.println(StaticDemo.i);
	}
}

class StaticDemo{
    static{
   	    i += 5;
    }
    static int i = 3;
}

结果:编译不通过

分析:当变量处于标记值状态,只能够赋值,不能够用于其他操作。在准备阶段,给i开辟内存空间,并且设定一个标记值,然后在初始化阶段直接进行相加的操作,因为i还是处于标记值状态,所以直接编译不通过。

public class StaticDemo3 {
	public static void main(String[] args) {
		System.out.println(StaticDemo.i);
	}
}

class StaticDemo{
 	static int i;
    static{
	    i = 5;
    }
}

结果:5

分析:在准备阶段,给i开辟内存空间,并且设定一个标记值。然后在初始化阶段先执行静态变量,再执行静态代码块将5赋值给i,并且舍弃标记值。所以结果就是5。

(9)例题

public class StaticDemo3 {
	public static void main(String[] args) {
		System.out.println(StaticDemo.i);
	}
}

class StaticDemo{
 	static{
		i = 5;
	}
	static int i = 3;
}
	

结果:3

分析:在准备阶段,给i开辟内存空间,并且设定一个标记值。然后在初始化阶段先执行静态代码块中的i=5的代码,舍弃标记值,将5赋值给i,再执行i = 3代码,将3赋值给i,所以结果就是3。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值