一、继承

Java中使用关键字extends表示继承,Java中所有的继承都是公共继承。

class Manager extends Employee
{
	//............
}



子类可以增加域、增加方法或者覆盖(重写)父类的方法,但不可以删除父类的任何域和方法。


子类覆盖父类方法时,访问权限不能比父类低,也即父类方法为public,则子类覆盖父类的方法也得为public。

在子类中,如果想调用父类中的方法,而不是当前类的方法,则可以使用关键字super。

public float getSalary()
{
	return super.getSalary() + bonus;
}



当然,对于子类的构造器,如果没有显式的调用父类的构造器,则会自动调用父类默认的构造器(没有参数的构造器)。


如果此时父类没有默认的构造器,则此时编译器会因为找不到父类的构造器而报错。

class Employee
{
	Employee(String name,int id)
	{
		//....................
	}
}

class Manager extends Employee
{
	Manager(String name,int id) //子类的构造方法没有显式调用父类构造器,且父类无默认的构造器,所以编译时会报错。
	{
		super.name = name ;
		super.id = id;
	}
}



多态:


一个对象变量可以引用多种实际类型的现象被称为多态。

Manager TempM = new Manager();

Employee TempE = TempM ;

TempE是Employee类型的,TempM是Manager类型的,Manager类继承了Employee类。

TempE不能使用Manager类的特有方法,也即父类引用不能使用子类的特有方法。子类转为父类的引用不需要强制转换。

public class Test21
{
	public static void main(String[] args)
	{
		Manager TempM = new Manager("zhangs",001);
		TempM.setBonus(500);
  	TempM.tobeString();
  	System.out.println(TempM.getSalary());
  	
		Employee[] staff = new Employee[3] ;
		staff[0] = TempM ;
		staff[0].tobeString();
	  //	staff[0].setBonus(1000);  //staff[0]是Employee类型,不能调用子类Manager的特有方法
	  System.out.println(staff[0].getSalary());
		
		staff[1] = new Employee("lisi",002);
		staff[1].tobeString();
		System.out.println(staff[1].getSalary());
		
		staff[2] = new Employee("wange",003);
		staff[2].tobeString();
		System.out.println(staff[2].getSalary());
		
		staff[0] = new Employee("hj",004);
		staff[0].tobeString();
		System.out.println(staff[0].getSalary());
		
		TempM.tobeString();
		
		Employee TempM1 = new Manager("zhangs1",005);
		System.out.println(TempM1.getSalary());
	}
	
}

class Employee
{
	public Employee(String name,int id)
	{
		this.name = name;
		this.id = id;
		nextId++;
		salary=1000.0f;
	}
	
	public void tobeString()
	{
		System.out.println(name+id+nextId);
	}
	
	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public int getId()
	{
		return id;
	}

	public void setId(int id)
	{
		this.id = id;
	}

	public float getSalary()
	{
		return salary;
	}

	public void setSalary(float salary)
	{
		this.salary = salary;
	}
	
	public static int getNextId()
	{
		return nextId ;
	}
	private String name;
	private int id;
	private static int nextId = 0; 
	private float salary ;
}


class Manager extends Employee
{
	Manager(String name,int id)
	{
		super(name,id);
		bonus=0 ;
	}

	public void tobeString()
	{
		System.out.println(super.getName()+super.getId()+super.getNextId()+bonus);
	} 

  public float getSalary()
  {
  	return super.getSalary()+bonus;
  }
	
	public void setBonus(float bonus)
	{
		this.bonus=bonus;
	}
	
	public float getBonus()
	{
		return bonus;
	}
		
	private float bonus;
}



动态绑定(未完全明白,JAVA2核心技术150页):


所谓动态绑定,也即编译器寻找具体执行方法的过程。

1、编译器查看对象的声明类型和方法名。

      例如调用方法X.f(),X是声明为A类对象,则编译器会搜索A类中所有方法名为f的方法,以及搜索类A的父类中,所有方法名为f且为public访问的方法。

2、编译器通过具体方法的参数类型,选择完全匹配的方法。1和2成为重载解析。

3、如果方法是final,private,static或者构造器,则编译器会很准确的找到该调用的方法,称为静态绑定。

4、程序运行,虚拟机会调用所引用对象的实际类型最合适的那个类的方法。这其实是一个搜索对应方法的过程,搜索耗时间,所以虚拟机会预先建立一个方法表


阻止继承:

对类使用final修饰或对方法使用final修饰可以阻止该类被继承或者该方法再被继承。

对象声明为final之后,只有其中的方法自动变为final,但域不会变为final。


强制类型转换:

将一个类型转换为另外一个类型的过程称为类型转换。

在类型强制转换过程中,如果条件不满足,可能抛出异常。

在进行类型转换之前,一般需要检查一下是否能够成功进行类型转换,使用instanceof运算符检查,如果不能转换,则编译器就不会执行转换操作。

if(staff instanceof Manager)
{
	TempM = (Manager)staff ;
}



类型转换


1、只能在编译层次内进行类型转换。

2、将超类转为子类之前,需要使用instanceof进行检查。