java类和实例的初始化问题

先上一个题:

public class Test08 {
	public static void main(String[] args) {
		Zi zi = new Zi();
	}
}
class Fu{
	private static int i = getNum("(1)i");
	private int j = getNum("(2)j");
	static{
		print("(3)父类静态代码块");
	}
	{
		print("(4)父类非静态代码块,又称为构造代码块");
	}
	Fu(){
		print("(5)父类构造器");
	}
	public static void print(String str){
		System.out.println(str + "->" + i);
	}
	public static int getNum(String str){
		print(str);
		return ++i;
	}
}
class Zi extends Fu{
	private static int k = getNum("(6)k");
	private int h = getNum("(7)h");
	static{
		print("(8)子类静态代码块");
	}
	{
		print("(9)子类非静态代码块,又称为构造代码块");
	}
	Zi(){
		print("(10)子类构造器");
	}
	public static void print(String str){
		System.out.println(str + "->" + k);
	}
	public static int getNum(String str){
		print(str);
		return ++k;
	}
}

会做嘛??????(嘻嘻嘻)

 

这里面包含继承,static关键字,静态代码块,非静态代码块,初始化顺序问题。

继承

首先说继承,子类继承父类,子类会继承父类的所有属性(PS:私有的属性虽然不能被直接的访问,但是可以间接的访问,在子类的堆信息中,也会存在父类的信息。对了还有若子类父类中有相同的属性,这两个属性由于没有重写所以,在堆中有两个名称相同的属性,)

(1)父类的所有的属性、方法都会继承到子类中。
  关于私有的属性和方法是否可以被继承到子类中?
  A:从在子类中可直接访问的角度来说:不能
  B:从子类具有的事物特征来说:可以
          即在子类对象的堆内存中,需要分配对应的内存,需要存储它的值,
         例如:学生对象中,需要分配name和age的内存,来存储学生的姓名和年龄。
 
  (2)父类的构造器无法继承到子类中。
  (3)子类的构造器中“必须”调用父类的构造器。
     默认情况下,调用父类的无参构造。不管你是否写了super()
     如果父类没有无参构造,那么子类“必须手动”调用父类的某个有参构造。使用super(实参列表)调用父类的有参构造。
 
      为什么要调用父类的构造器?
          要为从父类继承的属性进行初始化,那么父类的构造器中已经写了对应初始化代码,我们子类就不用重复,调用一下就可以了。
 
  (4)Java只支持单继承==>即只有一个亲生父亲
  (5)Java支持多层继承==>父类还可以有父类
  (6)一个父类可以同时有多个子类==》一个父亲可以同时有多个孩子
      子类还可以有子类        ==》代代相传
     
  (7)子类可以扩展父类没有的特征(属性和方法)
 (8)子类还可以对父类的“方法”进行“重写”

static

 2、static可以修饰什么
  (1)成员变量
      用它修饰的成员变量称为“类变量”或“静态变量”;
   不用它修饰的成员变量称为“实例变量”或“非静态成员变量”
   
  (2)成员方法
  用它修饰的成员方法称为“类方法”或“静态方法”
  不用它修饰的成员方法称为“实例方法”或“非静态方法”
 
  (3)代码块
  用它修饰的代码块称为“静态代码块”,“类初始化代码块”
  不用它修饰的代码块称为“非静态代码块”,“实例化代码块”,“构造块”
 
  (4)成员内部类
  用它修饰的成员内部类称为“静态成员内部类”,“静态内部类”
  不用它修饰的成员内部类称为“非静态成员内部类”,或者干脆就叫做“成员内部类”
 
  3、用它修饰的有什么不同
  总:用它修饰的成员,表示是属于“类”的,不单独属于“某个对象”。

 

初始化顺序

类的第一次加载可以通过哪些方式?

1.new对象

2.调用静态方法

3.使用子类对象

4.反射

类初始化和实例初始化的总结:
  (1)父类的类初始化
  (2)子类的类初始化
  (3)父类的对应的实例初始化
  (4)子类的对应的实例初始化
  A:顺序(1)(2)(3)(4)
  B:其中的(1)(2)只会执行一次;(3)(4)每new一个对象就执行一次。
  C:子类构造器中如果没有super()或super(实参列表)表示执行的是父类的无参的实例初始化方法<init>()
    如果子类的构造器中有super()或super(实参列表)表示执行对应的实例初始化方法
  D:如果在实例初始化过程中,涉及到调用某个方法,那么如果这个方法没有static修饰,要考虑是否被子类重写了。
                                  那么如果这个方法有static修饰,不会被重写,在哪个类中,就执行哪个类的。
    
   
    类初始化的方法的由两部分组成:
    (1)静态变量的显式赋值
    (2)静态代码块
    它俩按顺序执行。


    静态的代码块和静态的变量只执行一次


    实例初始化方法由三部分组成:
    (1)非静态变量的显式赋值
    (2)非静态代码块
    (3)构造器
    其中(1)和(2)按顺序,(3)在最后。但是(3)中的super()或super(实参列表)被组装到实例初始化方法中也在首行。、实例初始化什么时候执行?执行的特点是什么?
  (1)你每new一个对象,就会执行一个实例初始化方法。
           每次调用哪个实例初始化方法,看你调用哪个构造器。
  (2)要执行子类的实例初始化方法,会先执行父类相应的实例初始化方法

 

PS:无论是静态的初始化还是实例初始化,类在初始化的时候会提前的声明类中的变量,(不论修饰符)这个时候变量的值是默认值。就如下图在<clinti><inti>会先将变量放在最开始的位置,(即类里面的变量在类没有初始化的时候可以本类调用,这个时候为默认值

再上一个题:

public class Test12 {
	public static void main(String[] args) {
		Father3 f = new Father3();
		Son1 s = new Son1();
		System.out.println(f.getInfo());
		System.out.println(s.getInfo());
		s.setInfo("123");System.out.println(s.getInfo());
		System.out.println(f.getInfo());
		
	}
}
class Father3{
	private String info = "456";
	public void setInfo(String info){
		this.info = info;
	}
	public String getInfo(){
		return info;
	}
}
class Son1 extends Father3{
	
}

答案:
 

再来一个:

public class Test13 {
	public static void main(String[] args) {
		Father4 f = new Father4();
		Son3 s = new Son3();
		System.out.println(f.getInfo());
		System.out.println(s.getInfo());
		s.test();
		System.out.println("-----------------");
		s.setInfo("大硅谷");
		System.out.println(f.getInfo());
		System.out.println(s.getInfo());
		s.test();
	}
}
class Father4{
	private String info = "132";
	public void setInfo(String info){
		this.info = info;
	}
	public String getInfo(){
		return info;
	}
}
class Son3 extends Father4{
	private String info = "小硅谷";
	public void test(){
		System.out.println(this.getInfo());
		System.out.println(super.getInfo());
	}
}

答案:

 首先说明这里面s和f是两个对象,他们之间并没有关系,

       其次,由于子类中,没有重写任何的方法,所以代码中的getInfo()都是在调用父类中的方法,进行修改的,返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值