面向对象特征之二:继承
public class Person {
int age;
String name;
int sex;
public void showInfo() {
System.out.println(this.age);
System.out.println(this.name);
System.out.println(this.sex);
}
}
public class Student extends Person{
String school;
public void showInfo() {
System.out.println(this.school);
System.out.println(this.age);
System.out.println(this.name);
System.out.println(this.sex);
}
}
在Java 中,继承的关键字用的是“extends”,即子类不是父类的子集,而是对父类的“扩展”。
子类不能直接访问父类中私有的(private)的成员变量和方法
一个子类只能有一个父类
练习
1)定义一个ManKind类,包括
成员变量int sex和int salary;
方法void manOrWorman():根据sex的值显示“man”(sex1)或者“women”(sex0);
方法void employeed():根据salary的值显示“no job”(salary==0)或者“ job”(salary!=0)。
public class ManKind {
int sex;
int salary;
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public void manOrWomen() {
if (sex==1) {
System.out.println("man");
}else if(sex==0) {
System.out.println("women");
}
}
public void employeed() {
if (salary==0) {
System.out.println("no job");
}else {
System.out.println("job");
}
}
}
public class Kids extends ManKind {
int yearsOld;
public int getYearsOld() {
return yearsOld;
}
public void setYearsOld(int yearsOld) {
this.yearsOld = yearsOld;
}
public void printAge() {
System.out.println(this.yearsOld);
}
public static void main(String[] args) {
Kids someKid =new Kids();
someKid.setSalary(100);
someKid.setSex(0);
someKid.manOrWomen();
someKid.employeed();
}
}
//输出 women
// job
方法的重写
方法的重载
方法的重写:子类可以重新写父类的方法覆盖父类的方法。
修改练习1.1中定义的类Kids,在Kids中重新定义employed()方法,覆盖父类ManKind中定义的employed()方法,输出“Kids should study and no job.”
@Override
public void employeed() {
System.out.println("Kids should study and no job");
}
public static void main(String[] args) {
Kids someKid =new Kids();
someKid.setSalary(100);
someKid.setSex(0);
someKid.manOrWomen();//还是ManKids的方法
someKid.employeed();//这个方法是kids类的方法
四种访问修饰符
如果子类和父类在同一个包下,那么对于父类的成员修饰符只要不是private那都可以使用。
若果不在同一个包下,子类只能使用父类中protected和public修饰的成员
关键字super
@Override
public void employeed() {
//System.out.println("Kids should study and no job");
//修改练习1.1中定义的类Kids中employed()方法,在该方法中调用父类ManKind的employed()方法,
//然后再输出“but Kids should study and no job.”
super.employeed();
System.out.println("but Kids should study and no job.");
}
public static void main(String[] args) {
Kids someKid =new Kids();// new kids()是在调用kids类的默认无参构造方法,这个过程就会使用父类的构造方法
// someKid.setSalary(100);
// someKid.setSex(0);
//
// someKid.manOrWomen();
// someKid.employeed();
}//在父类添加一个无参构造方法,输出一句话,则子类运行结果会有这句话
this和super的区别
简单类对象的实例化过程
子类对象的实例化过程
1,先加载父类在加载子类
4,默认初始化,age,sex的值是0,name和school都是null
面向对象特征之三:多态性
在Java中有两种体现:
方法的重载(overload)和重写(overwrite)。
对象的多态性 ——可以直接应用在抽象类和接口上
Person e = new Student(); //父类引用对象可以指向子类的实例
但是以上不能使用子类声明的属性
方法可以调用(虚拟方法调用)
属性是在编译时确定的,编译时e为Person类型,没有school成员变量,因而编译错误。
编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法。——动态绑定
java的方法是运行在栈内存中,在运行方法时会动态进栈和出栈
instanceof操作符
检验某个对象是否为类A的子类
public static void main(String[] args) {
Student s=new Student();
Person p =new Person();
System.out.println(s instanceof Person);
}//输出 true
public static void main(String[] args) {
Student s=new Student();
Person p =new Person();
Person p1=new Student();
System.out.println(p1 instanceof Person);
System.out.println(p1 instanceof Student);
} //输出true
// true
Object类
多层继承,处于最高层的父类一定是Object类
public class Test {
/**
* 想给test方法设置一个形参参数,可以确定是一个类,但不确定是什么类,那么test方法的形参如何设置
*/
public void test (Object obj) {
}
public static void main(String[] args) {
Test t=new Test();
Person p =new Person();
Student s=new Student();
t.test(p);
t.test(s);
t.test(t);//调用方法时可以任意传递参数
}
}
public class Test {
/**
* 想给test方法设置一个形参参数,可以确定是一个类,但不确定是什么类,那么test方法的形参如何设置
*/
public void test (Object obj) {
}
public static void main(String[] args) {
Test t=new Test();
Person p =new Person();
Student s=new Student();
t.test(p);
t.test(s);
t.test(t);//调用方法时可以任意传递参数
System.out.println(p.equals(s));//判断是否同一个对象
Person e=new Student();
//以下方法是object类的方法,因为object是根父类
System.out.println(p.equals(e));//输出false,在堆里面生成了两个对象
//e=p的话,将p的引用交给e了,指向一个对象输出为true
Object o =new Object();
System.out.println(o.hashCode());//获得hash码
System.out.println(p.toString());//对象的内存地址
}
}
对象类型转换(Casting)
基本数据类型的Casting
自动类型转换:小的数据类型可以自动转换成大的数据类型 long g=20;
强制类型转换:可以把大的数据类型强制转换(casting)成小的数据类型
如 float f=(float)12.0; int a=(int)1200L
public static void main(String[] args) {
Student s=new Student();
Person p=s; //从子类到父类的类型转换可以自动进行
Person p1=new Person();
Student ss=(Student) p1;//从父类到子类的类型转换必须通过造型(强制类型转换)实现
}
==操作符与equals方法
public static void main(String[] args) {
Person p1=new Person();
Person p2=new Person();
System.out.println(p1.equals(p2));
}
当用equals()方法进行比较时,对类File、String、Date及包装类(Wrapper Class)来说,是比较类型及内容而不考虑引用的是否是同一个对象;用==比较。
String对象的创建
字面量创建对象省内存
==是比较对象内存地址,equals对于String对比的是内容
1,编写Order类,有int型的orderId,String型的OrderName,相应的getter()和setter()方法,两个参数的构造器,重写父类的equals()方法:public boolean equals(Object obj),并判断测试类中创建的两个对象是否相等
public class Order {
public Order(int orderld,String OrderName) {
this.orderld=orderld;
this.OrderName=OrderName;
}
int orderld;
String OrderName;
public int getOrderld() {
return orderld;
}
public void setOrderld(int orderld) {
this.orderld = orderld;
}
public String getOrderName() {
return OrderName;
}
public void setOrderName(String orderName) {
OrderName = orderName;
}
//重写方法 alt+/
//判断两个属性是否相等就可以判断对象是否相等
@Override
public boolean equals(Object obj) {
boolean flag=false;
if(obj instanceof Order) {
Order o=(Order) obj;
if(this.orderld==o.orderld && this.OrderName.equals(o.OrderName)) {
flag =true;
}
}
return flag;
}
}
public class Test {
public static void main(String[] args) {
Order o1=new Order(123, "aaaa");
Order o2=new Order(123, "aaaa");
System.out.println(o1.equals(o2));
}
}
2.请根据以下代码自行定义能满足需要的MyDate类,在MyDate类中覆盖equals方法,使其判断当两个MyDate类型对象的年月日都相同时,结果为true,否则为false。
public class MyDate {
public MyDate(int year,int mooth,int day) {
this.year=year;
this.mooth=mooth;
this.day=day;
}
int year;
int mooth;
int day;
@Override
public boolean equals(Object obj) {
int flag =1;
if(obj instanceof MyDate) { //传进来的object是不是MyDate类型
MyDate md =(MyDate) obj;
flag =0;
if(this.year!=md.year) {
flag+=1;
}
if(this.mooth!=md.mooth) {
flag+=1;
}
if(this.day!=md.day) {
flag+=1;
}
}
if(flag == 0) {
return true;
}else {
return false;
}
}
}
public static void main(String[] args) {
MyDate m1 =new MyDate(1996, 4, 21);
MyDate m2 =new MyDate(1996, 4, 21);
System.out.println(m1.equals(m2));
}
包装类Wrapper
基本数据类型包装成包装类的实例 —装箱
获得包装类对象中包装的基本类型变量 —拆箱
toString方法
父类Object的toString方法是输出对象的内存地址,如果想输出类的其他信息,重写toString
@Override
public String toString() {//想输出年月日
String str =this.year+" - "+this.mooth+" - "+this.day;
return str;
}
public static void main(String[] args) {
MyDate m1 =new MyDate(1996, 4, 21);
System.out.println(m1.toString());
}