一. Java语言的特性
封装:封装是指属性私有化,根据需要提供setter和getter方法来访问属性。即隐藏具体属性和实现细节,仅对外开放接口,控制程序中属性的访问级别。封装的目的是增强安全性和简化编程,使用者不必在意具体实现细节,而只是通过外部接口(此处的接口可以理解为某些访问私有属性的方法如JavaBean中的属性以及对应的getter和setter方法)即可访问类的成员。此时如果类中有一个带参的构造函数,那一定要写一个不带参的构造函数,以方便通过无参的构造函数实例化的对象使用成员方法。
继承:继承是指多个相同的属性和方法提取出来,新建一个父类。Java中一个类只能继承一个父类即子类和父类的关系是“is-a”关系,而一个父类可以被多个子类继承,而且子类不能继承父类中访问权限为private的成员变量和方法。子类可以重写父类中的方法,及命名与父类同名的成员变量,而且子类可以添加新的方法和属性。另外,子类不能继承父类的构造方法,但是子类可以通过super()来调用父类的构造方法。从而实现了代码的复用,但是应该尽量减少继承关系以降低代码的耦合度。
继承涉及内容:构造器,protected关键字,向上转型。
构造器:继承父类的属性和方法,除了那些private的外还有一样是子类继承不了的—构造器。对于构造器而言,它只能够被调用,而不能被继承。 调用父类的构造方法我们使用super()即可。对于子类而已,其构造器的正确初始化是非常重要的,而且当且仅当只有一个方法可以保证这点:在构造器中调用父类构造器来完成初始化,而父类构造器具有执行父类初始化所需要的所有知识和能力。
public class Person {
protected String name;
protected int age;
protected String sex;
Person(){
System.out.println("Person Constrctor...");
}
}
public class Husband extends Person{
private Wife wife;
Husband(){
System.out.println("Husband Constructor...");
}
public static void main(String[] args) {
Husband husband = new Husband();
}
}
Output:
Person Constrctor...
Husband Constructor...
通过这个示例可以看出,构建过程是从父类“向外”扩散的,也就是从父类开始向子类一级一级地完成构建。而且我们并没有显示的引用父类的构造器,但编译器会默认给子类调用父类的构造器。而且这个默认调用父类的构造器是有前提的:父类有默认构造器。如果父类没有默认构造器,我们就要必须显示的使用super()来调用父类构造器,否则编译器会报错:无法找到符合父类形式的构造器。
public class Person {
protected String name;
protected int age;
protected String sex;
Person(String name){
System.out.println("Person Constrctor-----" + name);
}
}
public class Husband extends Person{
private Wife wife;
Husband(){
super("chenssy");
System.out.println("Husband Constructor...");
}
public static void main(String[] args) {
Husband husband = new Husband();
}
}
Output:
Person Constrctor-----chenssy
Husband Constructor...
所以综上所述:对于继承而已,子类会默认调用父类的构造器,但是如果没有默认的父类构造器,子类必须要显示的指定父类的构造器,而且必须是在子类构造器中做的第一件事(第一行代码)。
对象的上转型对象:存在老虎类Tiger和动物类Animal,当我们说老虎是动物时,老虎就是去了它独有的属性和功能,只是具有动物的特性。 由此可以引申到Java语言的上转型对象。
Animal a = new Tiger();
或者
Tiger b = new Tiger();
Animal a = b;
如代码所示:我们成对象a是对象b的上转型对象(好比说“老虎是动物”)
上转型对象的特点:1. 上转型对象不能使用子类新增的成员变量和新增的方法。
2. 上转型对象可以操作子类继承或者隐藏的成员变量,也可以使用子类继承或者重写的方法。即上转型对象可以可以操纵父类原有的属性和功能,无论这些方法是否被重写。其作用等价于子类对象调用这些方法。因此,如果子类重写父类的方法后,当对象的上转型对象调用这个实例化方法时一定是调用了子类重写的实例方法,如图所示:
我们可以将图中的对象理解为Tiger的实例化对象b,对象的上转型对象可以理解为Animal的实例化对象a。
注:1. 可以将对象的上转型对象在强制转换为一个子类对象,这时候该子类对象又具备了子类所有的属性和功能,
即: Father father = new Son();//father是Son实例化对象的上转型对象。
Son son = (Son) father; //把上转型对象强制转换成子类的对象。
2. 不能将父类创建的对象的引用赋值给子类声明的对象(即不能说“人是美国人”)。
protected关键字:private访问修饰符,对于封装而言,是最好的选择,但这个只是基于理想的世界,有时候我们需要这样的需求:我们需要将某些事物尽可能地对这个世界隐藏,但是仍然允许子类的成员来访问它们。这个时候就需要使用到protected。对于protected而言,它指明就类用户而言,他是private,但是对于任何继承与此类的子类而言或者其他任何位于同一个包的类而言,他却是可以访问的。
public class Person {
private String name;
private int age;
private String sex;
protected String getName() {
return name;
}
protected void setName(String name) {
this.name = name;
}
public String toString(){
return "this name is " + name;
}
/** 省略其他setter、getter方法 **/
}
public class Husband extends Person{
private Wife wife;
public String toString(){
setName("chenssy"); //调用父类的setName();
return super.toString(); //调用父类的toString()方法
}
public static void main(String[] args) {
Husband husband = new Husband();
System.out.println(husband.toString());
}
}
Output:
this name is chenssy
多态:多态可以分为设计时多态和运行时多态。简单来说,多态就是同一事务,由于条件不同,产生的结果不同。而使用多态的原则是在声明变量或者是方法的参数列表时能用父类用父类,能用接口用接口。
设计时多态:即重载,是指Java允许方法名相同而参数不同(参数个数或者参数类型不同,返回值可以相同也可以不同)。
运行时多态:即重写,是指Java运行时根据调用方法的实际功能来决定调用哪个方法。从而实现了代码的灵活度,同时在使用多态时,优先调用子类的方法,如果子类没有重写父类的方法,则调用父类的方法。
多态的必要条件:继承,重写,向上转型(父类引用指向子类的实例化对象)
多态的使用过程:a. 定义子类extends父类,或者实现某接口,并重写父类中的方法;
b. 声明父类类型的实例化变量将其赋予子类类型的实例对象,即 Son son = new Father();
c. 调用相应的方法。使用多态时,父类在在调用方法时,优先调用子类的方法。如果子类没有重写父类的方法,则再调用父类的方法。
public class Wine {
public void fun1(){
System.out.println("Wine 的Fun.....");
fun2();
}
public void fun2(){
System.out.println("Wine 的Fun2...");
}
}
public class JNC extends Wine{
/**
* @desc 子类重载父类方法,父类中不存在该方法,向上转型后,父类是不能引用该方法的
* @param a
* @return void
*/
public void fun1(String a){
System.out.println("JNC 的 Fun1...");
fun2();
}
/**
* 子类重写父类方法
* 指向子类的父类引用调用fun2时,必定是调用该方法
*/
public void fun2(){
System.out.println("JNC 的Fun2...");
}
}
public class Test {
public static void main(String[] args) {
Wine a = new JNC();
a.fun1();
}
}
Output:
Wine 的Fun.....
JNC 的Fun2...