Static块、构造器在父类和子类中的执行顺序
代码:
public class Fruit {
static String id = "fruit000";
public Fruit(){
System.out.println("Fruit");
}
static{
System.out.println(id);
}
}
public class Orange extends Fruit{
static String id = "orange110";
public Orange(){
System.out.println("Orange");
}
static{
System.out.println(id);
}
public static void main(String[] args){
Orange orange = new Orange();
}
}
结果:
fruit000
orange110
Fruit
Orange
结果分析:
1、调用顺序:
JAVA类首次装入时,会对静态成员变量或方法进行一次初始化,但方法不被调用是不会执行的,静态成员变量和静态初始化块级别相同,非静态成员变量和非静态初始化块级别相同。
先初始化父类的静态代码--->初始化子类的静态代码-->
(创建实例时,如果不创建实例,则后面的不执行)初始化父类的非静态代码--->初始化父类构造函数--->初始化子类非静态代码--->初始化子类构造函数
其他说明:
2 、类只有在使用New调用创建的时候才会被JAVA类装载器装入
3、创建类实例时,首先按照父子继承关系进行初始化
4、类实例创建时候,首先初始化块部分先执行,然后是构造方法;然后从本类继承的子类的初始化块执行,最后是子类的构造方法
5、类消除时候,首先消除子类部分,再消除父类部分
总结就是,先静态后非静态。态中先父后子。非静态先成员变量后构造函数。
别名现象
代码:
public class Car {
public String name = "";
}
public class BieMing {
public static void main(String[] args) {
// TODO Auto-generated method stub
Car a = new Car();
Car b = new Car();
a.name = "dazhong";
b.name = "bieke";
System.out.println("a.name: "+ a.name + "\nb.name: "+ b.name);
b = a;
b.name = "laosilaisi";
System.out.println("a.name: "+ a.name + "\nb.name: "+ b.name);
}
}
结果:
a.name: dazhong
b.name: bieke
a.name: laosilaisi
b.name: laosilaisi
结果分析:
由结果可知,我们真正操作的是对对象的引用。所以,上述代码中 b=a,实际上就是把引用a复制给了b,那么他们指向的对象就是原来a所指的对象。
自增问题
代码:
public class Plane {
public static void main(String[] args){
int a = 0;
int b = 0;
System.out.println(a);//0
System.out.println(a++);//0
System.out.println(a);//1
System.out.println(++a);//2
System.out.println(a);//2
System.out.println(b=(++a)+1);//4
System.out.println(a);//3
}
}
注释部分为对应行的运行结果,前缀先自加再运算,后缀先运算再自加。
覆盖和重载
分析:
覆盖就是你觉得父类的方法不能满足子类的服务需求,于是重写(覆盖)了父类的方法。自然,子类覆盖的方法的返回类型,方法名和参数列表要和父类中的方法相同。访问权限不能低于父类的。抛出的异常不能多于父类。这样,子类只能覆盖一次父类的方法了。
重载可以发生于子类或者父类中。《Thinking in Java》,将方法名和参数列表定义为方法的签名。方法名相同,但参数列表不同(包括顺序不同),都属于重载。
由此可见,覆盖有更多的条件。
继承和protected
分析:
Protected | 允许包内访问,允许子类访问 |
Public | 允许访问 |
Private | 类私有 |
默认 | 允许包访问 |
Final和private
分析:
final锁定数据、方法、类,表示不再修改。继承时,方法不允许覆盖,类不能被继承。
类中所有的private方法都隐式地指定为final。
This和super
分析:
This的两种用法:
一:对自身类对象的引用
二:调用被重载的构造函数
Super的两种用法:
一:调用父类的构造函数
二:调用父类的方法(private不能调用)
示例:
public class Person {
private String name;
protected String age = "22";
public String id = "001";
String tall = "175";
public Person(){
this.name = "Shirman";
}
public Person(String name,String age){
this.name = name;
this.age = age;
}
private String getName() {
System.out.println(name);
return name;
}
protected String getAge() {
System.out.println(age);
return age;
}
public String getId() {
System.out.println(id);
return id;
}
String getTall() {
System.out.println(tall);
return tall;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
public class Teacher extends Person{
private String subject;
private int office;
public Teacher(){
this.subject = "Science";
}
public Teacher(String subject){
this.subject = subject;
}
public Teacher(String name,String age,String subject){
super(name,age);//super调用父类的构造器,避免代码重复。
this.subject = subject;
}
public Teacher(String subject,int officeIn){
this(subject);//this的第二种用法。调用合适的构造器,避免代码重复。
this.office = officeIn;
}
public String getSubject() {
super.getAge();//super调用父类方法
return this.subject;
}
public int getOffice() {
return this.office;
}
public static void main(String[] args) {
Teacher t = new Teacher();
t.getSubject();//调用getSubject方法时,方法中的this此时和t同时指向同一个Teacher对象
}
}
Static
分析:
静态,跟类有关,和类对象的数量无关,即只有一个存储空间。类对象共享静态变量或者方法。或者说静态成员对所有该类对象来说是公共的。
多态(和向上转型有关):
多态也成为动态绑定、后期绑定、或运行时绑定。Java除了static方法和final方法(private属于final方法)之外,其他都是后期绑定。数据成员属于前期绑定。
某个子对象要以来于其他对象,销毁的顺序应该和初始化顺序相反。对于字段,则意味着与声明顺序相反。对于基类,应该首先对导出类进行清理,然后才是基类。