5.1面向对象的高级特性之二:继承
public class person{
public int age;
public String name;
public int sex;
public void showInfo(){
System.out.println(this.age+this.sex+this.name);
}
}
public class Student extends person{
String school;
@Override
public void showInfo() {
System.out.println(this.age+this.sex+this.name+this.school);
}
}
用关键字extends继承
子类的共性代码都是继承自父类的,每个子类只要写自己的特有代码即可。 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无须再定义这些属性和行为,只要继承拿个类即 可。 此处的多个类称为子类,单独的整个类称为父类(基类或超类) 语法:class Subclass extends Superclass{}
继承的作用:
1.继承的出现提高了代码的复用性 2.继承的出现让类与类之间产生了关系,提供了多态的前提 3.不要仅为了其他类中的某个功能去继承。
子类继承父类,就继承了父类的方法和属性 在子类中,可以使用父类中定义的方法和属性,也可以创建新的属性和方法。 子类不是父类的子集,而是对父类的扩展extends 类继承的规则:子类不能直接访问父类中的私有private的成员变量和方法。 java只支持单继承不支持多继承,但java支持多层继承。
练习:
定义一个Mankind类,包括:成员变量int sex和int salary方法void manOrWoman():根据sex的值显示“man”sex=1或者woman sex=0,方法void employeed()根据salary的值显示“no job”salary=0或者“job”salary!=0定义类Kids继承Mankind类,并包括成员变量int yearsOld;方法printAge()打印yearsOld的值。在Kids类的main方法中实例化Kids的对象someKid,用该对象访问其父类的成员变量和方法。
public class Mankind{
public int sex;
public int salary;
public void manOrWoman(){
if(sex==1)
System.out.println("man");
else if(sex==0)
System.out.println("woman");
else
System.out.println("error!!!");
}
public void employeed(){
if(salary==0)
System.out.println("no job");
else
System.out.println("job");
}
}
public class Kids extends Mankind {
int yearsOld;
public void printAge(){
System.out.println(this.yearsOld);
}
public static void main(String[] args) {
Kids kids=new Kids();
kids.sex=1;
kids.salary=1000;
kids.yearsOld=20;
kids.printAge();
kids.employeed();
kids.manOrWoman();
}
}
练习:
根据下图实现类,在TestCylinder类中创建Cylinder类的对象,设置圆柱的底面半径和高,并输出圆柱的体积
public class Circle {
private double radius;
Circle(){
radius=1;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public double findArea(){
return 3.14*radius*radius;
}
}
public class Cylinder extends Circle{
private double length;
Cylinder(){
length=1;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double findVolume(){
return findArea()*this.length;
}
}
public class TestCylinder {
public static void main(String[] args) {
Cylinder cylinder=new Cylinder();
cylinder.setLength(2);
cylinder.setRadius(2);
System.out.println(cylinder.findVolume());
}
}
5.2方法的重写override
在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置、覆盖。在执行程序时,子类的方法将覆盖父类的 方法。 要求: 1.重写方法必须和被重写方法具有相同的名字、参数列表和返回值类型----只是重写方法体 2.重写方法不能使用比被重写方法更严格的访问权限 3.重写和被重写的方法必须同时为static或同时为非static 4.子类方法抛出的异常不能大于父类被重写方法的异常
5.3super关键字
在java中使用super来调用父类中的指定操作: 1.super可用于访问父类中定义的属性 2.super可用于定义父类中定义的成员方法 3.super可用于在子类中调用父类的构造器 tips: 尤其当子父类出现同名的成员时,可以用super进行区分 super的追溯不仅限于直接父类 super和this的用法相似,this代表本类对象的引用,super代表父类的内存空间的标识。
5.4面向对象高级特性之三:多态
多态性,是面向对象中最重要的概念,在java中多态有两种体现: 1.方法的重载(overlord)和方法的重写(override) 2.对象的多态性----可以直接应用在抽象类和接口上 java引用变量有两个类型:编译时类型和运行时类型,编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变 量的对象决定。 若编译时类型和运行时类型不一致,就出现多态(polymorphism )----对象的多态 对象的多态:在java中,子类的对象可以替代父类的对象使用 1.一个变量只能有一种确定的数据类型 2.一个引用类型变量可能指向(引用)多种不同类型的对象 子类可以看做是特殊的父类,所以父类类型的引用可以指向子类的对象:向上转型(upcasting) Person p=new Person(); Person e=new Student(); Person p=new Perosn(); p=new Student();//p指向的是Student实例化对象 一个引用类型的变量如果声明为父类的类型,但实际引用的是子类的对象,那么该变量就不能再访问子类中添加的属性和方法。 Student m=new Student(); m.school="PKU";//合法,Student类有school成员变量 Person e=new Student(); e.school="ABC";//不合法,Person类中没有school 成员变量 属性是在编译时确定的,编译时e为Person类型,没有school成员变量,因此编译错误。 方法:虚拟方法调用(Virtual Method Invocation) 正常的方法调用: Person p=new Person(); p.getInfo(); Student s=new Student(); s.getInfo(); 虚拟方法调用(多态情况下): Person e=new Student(); e.getInfo();//调用的Student类的getInfo()方法 编译时类型和运行时类型 编译时e为Person类型,而方法的调用时在运行时确定的,所以调用的是Student类的getInfo()方法。———动态绑定。 多态小结: 前提: 需要存在继承或实现关系 需要有覆盖操作 成员方法:成员方法的多态性,也就是动态绑定,必须得存在于方法的重写之上 编译时:要查看引用变量所属的类中是否有所调用的方法。 运行时:调用实际对象所属的类中的重写方法。 成员变量: 不具备多态性,只看引用变量所属的类。 子类继承父类: 1.若子类重写了父类的方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类的方法转移到子类 中 2.对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义 的实例变量 instanceof操作符: X instanceof A:检验X是否为类A的对象,返回值为boolean型 要求X所属的类与类A必须是子类和父类的关系,否则编译错误。 如果X属于类A的子类B,X instanceof A值也为TRUE。
5.5object类、包装类
object类是所以java类的根父类 如果在类的声明中未使用extends关键字指明其父类,则其默认父类为object类 object类 定义一个方法时, method(Object a ){...}表示method可以接受任何类的参数
object类中的主要方法:
Object s=new Student();
Object p=new Person();
构造方法:Object()
对象比较:public boolean equals(Object object)
Person p=new person();
Student s=new Student();
System.out.println(p.equals(s));//false
Person e=new person();
System.out.println(p.equals(e));//true
取得Hash码:public int hashCode()
Person p=new person();
System.out.println(p.hashCode());
对象打印时调用:public String toString()
Person p=new person();
System.out.println(p.toString());
5.6对象类型转换casting
基本数据类型的转换Casting: 自动类型转换:小的数据类型可以自动转换成大的数据类型
强制数据类型转换:可以把大的数据类型强制转换Casting成小的数据类型
对java对象的强制类型转换称为造型: 从子类到父类的类型转换可以自动进行 从父类到子类的类型转换必须通过造型(强制类型转换)实现 无继承关系的引用类型间的转换是非法的
==操作符和equals方法 ==: 基本类型比较值:只有两个变量的值相等,即为TRUE 引用类型比较引用(是否指向同一个对象):只有指向同一个对象时,==才为TRUE 用==进行比较时,符号两边的数据类型必须兼容(可自动转换的基本数据类型除外),否则编译错误 equals:
所有类都继承了object,也就获得了equals()方法,还可以重写 只能比较引用类型,其作用与==相同,比较是否指向了同一个对象。 格式:obj1.equals(obj2); 特例:当用equals方法进行比较时,对类File、String、Date类及包装类(Wrapper Class)来说,是比较类型及内容而不 考虑引用的是否是同一个对象: 原因:在这些类中重写了object类中的equals方法 包装类(Wrapper)--主要为了基本数据类的与字符串之间的转换
针对八种基本定义相应的引用类型---包装类(封装类) 有了类的特点,就可以调用类中的方法 基本数据类型——包装类 boolean——Boolean byte——Byte short——Short int——Integer long——Long char——Character float——Float double——Double
基本数据类型包装成包装类的实例---封箱 通过包装类的构造器实现: int i=500;
Integer t=new Integer(i); 还可以通过字符串参数构造包装类对象: Float f=new Float("4.56"); Long l=new Long("asdf");//报错NumberFormatException 获得包装类对象中包装的基本类型属性--拆箱 调用包装类的.xxxValue()方法; boolean b=bObj.booleanValue(); JDK1.5之后,支持自动装箱,自动拆箱。但数据类型必须匹配。 字符串转换成基本数据类型: 通过包装类的构造器实现: int i=new Integer("12"); 通过包装类的parseXxx(String s)的静态方法: Float f=Float.parseFloat("12.1"); 基本数据类型转换成字符串: 调用字符串重载的valueOf()方法 String fstr=String.valueOf(2.34f); 更直接的方法: String intstr=5+""; toString()方法: object类的toString方法是输出当前对象的内存地址,如果要输出别的信息,则需要重写toString方法。