本人大二计算机专业,想在寒假期间把java学过的知识给总结一下,边学习边总结总是好的。希望各位朋友大牛看过之后可以给出意见,欢迎大家一起讨论交流,一起进步。文章内容可参考《Java核心技术》。
本文具体介绍一下类、超类和子类的关系以及Object类的特性。
首先,类是java中比较重要的一个概念,类似于对一组拥有共同特征和功能的事物的抽象描述。
超类(父类)和子类可以对应数学中集合的关系。可以说,子类包含超类。当然,在java中是子类继承了超类或者父类,但并不代表超类比子类拥有更多的功能或者更详细的描述,恰恰相反,子类拥有的功能更丰富。例如,在公司中有雇员和经理,当然经理也是雇员。经理继承了雇员的一些基本特征:上班,下班,获得每月工资。当然经理还有着自己所特有的方法:获得年终奖等。
在子类代码中,超类的成员变量和方法一样可以调用。应注意使用super关键字来调用超类中的该方法,否则默认是调用本类的方法。注意:super不是一个对象的引用,不同于this是本对象的引用,它只是编译器中调用超类方法的特殊关键字。
在子类的构造方法中,super(参数)则是调用了超类有参的构造方法。若子类中没有显式的调用超类构造方法,则会自动调用超类的无参构造方法。
超类中被private修饰的成员变量,在子类中只能通过super.get方法引用,其余修饰的变量则可以直接引用。
this作用有两个:一是引用隐式参数,二是调用该类其他的构造器。super作用也是两个:一是调用超类的方法,二是调用超类的构造器。其中super调用构造器必须是作为子类构造方法的第一条语句出现!
在子类中可以覆盖重写超类中的方法,通过添加@Override实现。
//Employee类方法
@Override
public void method() {
System.out.println("子类方法");
}
//Person类方法
public void method()
{
System.out.println("父类方法");
}
Employee e = new Employee(); //创建对象
e.method();
输出:
子类方法
若一个方法在多个类中被实现,JVM在程序执行前就知道该调用哪个类中的方法称为静态绑定。编译器会在方法调用的时候,列出超类和子类的方法表,在其中匹配方法的签名(方法名称和参数列表)。优先调用子类方法,没有则向上查找,这称为动态绑定。
被final修饰的类无法继承其他的父类,被final修饰的方法无法被其子类覆盖重写(final类中的所有方法自动地成为final方法)。
封装性是忽略方法的实现细节,强调方法的功能,对外提供调用的实现接口,对封装的内部进行保护,防止被外部修改,限制外部对属性的访问。
继承性是类与类之间的关系,抽取多个类所共有的特征和方法,定义为超类,并继承超类。Java中不允许多继承,即一个类继承了多个父类(在现实生活中一个儿子不会有多个父亲)。但允许多重继承,即儿子——父亲——爷爷。
多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术。
Person p = new Employee(); //左边是超类,右边是子类的构造方法。
举个例子:
别人举行婚宴请你们家喝喜酒,请帖上写着你父亲的名字,实际上你父亲去也可以,你去也可以,你妹妹去也可以,因为你们都是一家人,都可以代替你父亲。在婚礼举行之前,谁也不知道你们家到底谁会去,只是确定是你们家人去参加。
注意:
当使用多态方式调用方法时,首先检查父类中是否存在该方法,若存在则检查子类,子类也存在则调用子类方法;否则调用父类方法。若父类不存在该方法,即使子类中存在,也会报错。
在继承的层次中,祖先类在其子类中通用性更强,但因为祖先类的对象功能和特性太少,不足以描述一个实例,人们只想将其作为其他类的基类,而不是一个特定的实现类。这样祖先类中的方法内容便无关紧要,只需要保留着方法接口即可,其内容则可以在子类中覆盖重写。这样的祖先类成为抽象类。
抽象类不能够直接new对象,因为已经忽略了该类的实例化,只保留其基本功能接口。需要创建实现类对象来继承抽象类,并覆盖重写其中的方法。需要注意,可以定义一个抽象类的对象变量,但是它只能引用实现类(非抽象子类)的对象。
Person p = new Employee();
这里p还是定义了一个抽象类Person的变量,但p是实现类Employee对象的引用。
public:对所有类可见
protected:对本包和所有子类可见
不写修饰符:对本包可见
private:对本类可见
Java所有类都继承Object类,所以所有类都可以调用Object类中的方法:equals(),toString(),hashCode()。
判断两个对象是否有相同的引用。在重写方法之前,equals()则是比较两个引用是否有相同的地址值,与“==”的效果相同。重写后则会比较两个引用是否有相同的内容。
Person p2 = new Person("赵丽颖",19);
Person p1 = new Person("赵丽颖",19);
System.out.println(p1==p2);
System.out.println(p1.equals(p2));
输出:
false
false //这里我们创建两个相同内容的对象,但是其地址不同
//类似与C语言中两个指针指向的地址不同。
在重写后
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
输出:
false
true //这里就是比较的内容
重写之前直接打印对象,则会返回该对象的字符串表示。IDEA自动重写功能则会输出对象的属性值。
在日常开发的过程中,重写toString()方法是很必要的。这样可以直观看到对象状态的必要信息。
例如:
Person p = new Person("赵丽颖",19);
System.out.println(p);
输出:
demo0Review.Person@7ef20235
如果重写了toString方法
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
输出:
Person{name='赵丽颖', age=19} //该对象的属性
两个相等的对象则会返回相同的散列码。
如果重写了equals()方法,一定要重写hashCode()方法,保正两个属性相同的对象散列值相等。