一,静态语句块的定义
在一个类中,不属于任何方法体并且以static关键字修饰的语句块,称为静态语句块。
因为静态语句块常用来进行类变量的初始化,所以也称为静态初始化程序块。
格式:static{ };
♦静态语句块在加载该类时执行一次(此处的类加载是在该类被调用时才进行加载,比如:当要验证的语句和main()方法在一个类中时,此时调用main()方法时,要先对该类进行加载才能调用main()方法,但是若main()方法和要验证的语句不在一个类中时,则先进行main()方法的类的加载和main()方法的调用,然后当后面要调用放了要验证的语句的类时(即new该类对象时),验证类才会被加载)如果一个类中定义了多个静态语句块,则这些语句块将按在类中出现的先后次序运行。
二, 程序初始化的优先级: 基类>派生类
static>实例块
即:先执行基类中的static,在执行派生类中的static,在执行基类中的实例块,在执行派生类中的实例块。
♦(前两种static,谁在前,先打印谁)
1.private static int i; //静态变量
2.static{ i=5 }; //静态语句块
3. public static int a(){ //静态方法
};
♦ 静态语句块,静态变量在类加载时运行,静态方法在手动调用时才执行。
♦实例块包括: int i=0; { };(这两个按先后次序执行)
构造函数 (一般最后执行)
♦实例块只有在新new对象后,才执行。
三,代码实现 -1:
1 public class ObjectInitTest { 2 { 3 System.out.println("实例块a"); 4 } 5 static{ 6 System.out.println("b"); 7 } 8 9 private int a= methoda(); 10 private static int b=methodb(); 11 private static int c=4; 12 13 private static int methodb() { 14 System.out.println("静态属性b"); 15 System.out.println(b); 16 return 9; 17 } 18 private int methoda() { 19 System.out.println("属性a"); 20 return 8; 21 } 22 private static void methodc() { 23 System.out.println("静态属性c"); 24 } 25 26 27 public ObjectInitTest(int a,int b) { 28 this.a=a; 29 this.b=b; 30 } 31 32 { 33 System.out.println("实例块b"); 34 System.out.println(a); 35 } 36 37 public static void main(String[] args) { 38 39 ObjectInitTest o=new ObjectInitTest(1,2); 40 //System.out.println(a); //直接调用a和methoda()会出错,因为静态方法不能直接访问所属类的非静态变量和方法 41 //System.out.println(o.methodc()); 42 System.out.println(o.methoda());
System.out.println(o.a); //非静态变量和方法的访问,需要通过对象 43 System.out.println(b); //此处b为静态变量,可在main的静态方法中直接访问 44 } 45 }
运行结果及分析
分析:
应注意问题:
1, 因为静态方法的调用不是通过实例对象进行的,静态方法是类级别的,所以在静态
方法中没有this指针,且不能直接访问所属类的非静态变量和方法,只能访问方法内定义的
局部变量,自己的参数和静态变量。非静态变量和方法的访问,需要通过对象。
2,main()方法是一个静态方法。如果要在main()方法中访问所在类的成员变量或方法,就必须首先创建相应
的实例对象。否则只能访问静态方法或变量。
3,static变量只能用static方法给其赋值,但普通变量随意。
三,代码实现-2
1 package L13; 2 class A{ //父类 3 protected int a; 4 protected int c; 5 6 public A(int a){ 7 this.a=a; 8 this.c=1; 9 System.out.println("父类构造函数"); 10 } 11 static{ //静态语句块 12 System.out.println("父类静态语句块"); 13 14 } 15 { 16 System.out.println("父类实例语句块"); 17 } 18 public void show(){ 19 System.out.println("父类方法"); 20 System.out.println("a:"+a); 21 } 22 public void show1(){ 23 System.out.println("父类独有的方法"); 24 } 25 } 26 /** 27 * 派生类B有两部分 28 * 1.从基类继承来的成员(可重新初始化) 29 * 2.自己定义的成员 30 * 31 * super和this都必须写在第一行 32 * super(); //在派生类中调用基类构造函数,在派生类方法中必须写在首行 33 * super.方法名();//在派生类中,当继承下来的基类方法被派生类重写,在派生类中可用super.方法名()来调用基类的方法。 34 */ 35 class B extends A{ //B继承A类 36 private int a; 37 private int b; 38 public B(){ 39 super(3); //调用父类的构造方法 40 this.a=2; 41 this.b=2; 42 System.out.println("子类构造函数"); 43 } 44 static{ //静态语句块 45 System.out.println("子类静态语句块"); 46 47 } 48 { 49 System.out.println("子类实例语句块"); 50 } 51 public void show(){ 52 System.out.println("子类方法"); 53 System.out.println("a:"+a); //当父类和子类拥有相同变量时,若直接用a 打印的是子类中的a变量的值 54 System.out.println("a:"+super.a); //若用super.a调用,当在子类中没有对其进行初始化,则打印的就是父类中变量a的值。 55 //若以初始化,则打印的是初始化后的。 56 System.out.println("c:"+c); //但子类中没有与父类重复的变量,可直接用c打印变量值。 57 } 58 public void test(){ 59 super.show(); // 与变量类似,对于被子类重写了的方法,需用super.方法名()来掉用 60 this.show1(); //对于父类独有的,直接掉用。 61 this.show(); 62 } 63 } 64 public class DeriveTest { 65 public static void main(String[] args) { 66 B b=new B(); 67 //b.show(); //因为子类方法名与父类相同,且返回值与参数列表也相同,所以被B继承的父类的show()方法已被子类相同方法重写 68 //所以b.show()打印出来就是子类中show()方法的内容。 69 //b.show1(); //但对于父类独有的方法,当被B类继承下来后,因为没有被重写,所以 b.show1();打印出来的就是父类中方法的内容。 70 // b.test(); 71 B c=new B(); 72 } 73 74 }
运行结果:
需注意:
* this关键字的两个用法:
* 1.在构造函数中调用待传入int参数的其它的构造函数,如this( )。
* 2.在成员方法里面访问其它成员(变量,方法),前面可以添加this.变量/方法。
*
* super关键字的三个用法:
* 1.在派生类的构造函数中调用基类的带int参数的构造函数 如super( )。
* 2.super.func() 在派生类中,调用从基类继承来的func方法
* 3.super.a 在派生类中,调用从基类继承来的名字叫a的成员变量
super关键字
在对象的内部使用,可以代表父类对象
1,访问父类的属性 super.age
2,访问父类的方法 super.eat()
3,子类的构造过程中必须调用其父类的构造方法 super();
( 如果子类的构造方法中没有显式调用父类的构造方法,则系统默认调用父类无参的构造方法
如果显式的调用构造方法,必须在子类构造方法的第1行
如果子类构造方法中既没有显示调用父类的构造方法,而父类有没有无参的构造方法,则编译出错。)
this和super关键字都和对象有关,所以在static方法中不能使用这两个关键字