Java类的继承

可以让一个类继承自另一个类,此时该类会继承另一个类中的属性和方法,这样可以少写很多代码

类继承语法规则

< 修饰符> class < 子类名称> [extends < 父类>]
{
<属性和方法的声明>

类的继承

子类继承了父类,就继承了父类的方法和属性。(子类对象可以调用父类属性、方法)
在子类中,可以使用父类中定义的方法和属性,也可以创建新的数据和方法。
因而,子类通常比父类的功能更多,而是对父类的“扩展”。
在Java中,继承的关键字用的是“extends”,即子类不是父类的子集,而是对父类的“扩展”。

继承规则

Java只支持单继承,不允许多重继承
  一个子类只能有一个父类
  一个父类可以派生出多个子类
子类不能继承父类中私有的(private)的成员变量和方法,不能直接访问【可以调用父类的public或者protect方法去访问】

示例

父类

package com.uncleyong;

import java.util.Date;

public class Person {
public String name;
public int age;
public Date birth; private String lover = "lucy"; public String getInfo(){
return "name: " + name + ", " +
"age: " + age + ", " +
"birth: " + birth+ ", " +
"lover: " + lover;
} }

子类 

package com.uncleyong;

public class Student extends Person{
public String school;
}

测试类

package com.uncleyong;

import java.util.Date;

public class TestPerson {
public static void main(String[] args) {
Student student = new Student();
student.name = "Jerry";
student.birth = new Date();
student.age = 1;
student.school = "清华";
System.out.println(student.getInfo()); Person person = new Person();
person.age = 1;
person.birth = new Date();
person.name = "Tom"; System.out.println(person.getInfo());
}
}  

访问控制

可以对Java类中定义的属性和方法进行访问控制----规定不同的保护等级: public、protected、default、private

default就是什么都不加
子类,就是可以跨包【因为子类可能跨包,所以,为了使父类中属性、方法在子类能访问,父类最严格的访问控制只能是protected】

//仅在类的内部可以访问.
private String email; //在同一个包内该属性可以被访问.
String major; //在子类中该属性可以被访问, 且该子类可以跨包(不在同一个包下)
//如果不是子类,跨包不能访问;如果不是子类,在同一个包下的类,也可以访问
protected int salary; //访问权限最高, 无论是否在一个包内, 无论是否是子类都可以被访问.(在一个项目中都可以被访问)
public String name;
public int age;
public Date birth;

方法的重写、覆盖

在子类中可以根据需要对从父类中继承来的方法(构造方法不能被继承)进行改造—覆盖方法(方法的重置、重写),在程序执行时,子类的方法将覆盖父类的方法。

覆盖方法必须和被覆盖方法具有相同的方法名称、参数列表和返回值类型。【返回类型、方法名、参数列表必须完全相同,应用场景:继承,父类的成员方法只能被它的子类重写】

  如果参数个数不一样,就是方法的重载了(一个从父类继承的,一个自己类里写的,会根据调用方法时的传参,确定是调继承的,还是自己类里的),但是重载是不是要在一个类中的方法呢?【结果验证:可以在不同的类中,比如父类,虽然一个是父类,但是子类继承了,子类也就有了父类的方法】,见下面验证示例:

  返回值类型必须一样,否则两个方法不知道该调用哪个(一个从父类继承的,一个自己类里写的),方法名、参数列表都一样了,只有返回类型不一样,编译的时候报错返回类型不兼容

覆盖方法不能使用比被覆盖方法更严格的访问权限。

参数个数不一样,验证:

父类:Test.java

package com.test;

public class Test {
public int i;
public void t(){
System.out.println("test");
}
}

子类:Test2.java

package com.test;

public class Test2 extends Test{
public void t(String s){ // 这个方法和父类t方法相比,多了一个形参,所以不是方法重写,而是方法重载
System.out.println(s);
}
public static void main(String[] args) {
Test2 test2 = new Test2();
test2.t("qzcsbj"); // qzcsbj
test2.t(); // test
}
}

关于构造方法的重载、重写

父类构造方法不能被子类继承:因为如果子类继承了父类的构造方法,父类的构造在子类中不符合构造方法的规则,也不符合一般方法的规则,因为父类的构造在子类中没有返回类型,方法名也与子类的类名不相同。不符合java语法规范。继承就跟我们现实中的父子关系差不多,要有一个孩子对象那么就得先有一个父亲<会调用父类的构造方法>,所以会执行父类构造方法。另一种如果你想调用父类的带参数构造方法,那还得通过super关键字来调用<super后面括号中加上参数;如果父类构造是无参的,子类也默认调了,在子类的默认构造方法中有一句super();>。构造方法是不能继承的,想想如果能继承,那不是孩子也能构造父亲了;见下方验证示例

父类构造方法不能被子类重写(因为不能继承);

父类构造方法不能被子类重载(因为不能继承,子类就不具有这个方法;在java中类的构造函数与类的名称相同,不可能子类和父类使用相同的类名称,因此子类也就不能重载父类的构造函数,但子类可以通过super来调用父类的构造函数);

子类可以重载从父类继承过来的方法;

子类可以重载自己默认的构造方法;

子类可以重载父类的非构造方法:可以这样理解,子类继承了父的方法,子类本身也就有了这个方法。在子类写一个只多了一个参数其余都一样的方法,就是重载了继承的这个方法,实际也是在一个类中。

父类构造方法不能被子类继承,验证:

父类:A.java

package com.qzcsbj;

public class A {
public A(){
System.out.println("父类构造方法");
}
public void test(){
System.out.println("父类A测试方法");
}
}

子类:B.java

package com.qzcsbj;

public class B extends A {
public int age;
public B(){
System.out.println("子类构造方法");
}
public void test(int a){
System.out.println("子类B测试方法");
} public static void main(String[] args) {
B b = new B();
b.test();
b.test(1);
}
}

输出结果:

父类构造方法
子类构造方法
父类A测试方法
子类B测试方法 

上面说明:父类中的构造方法是不能继承的,但是在实例化子类的时候会调用父类的构造方法,每个子类构造方法的第一条语句,都是隐含地调用super()

重写示例

package com.uncleyong;

/**
* 定义一个ManKind类,包括
* 成员变量 int sex 和 int salary;
* 方法 void manOrWorman():根据sex的值显示“man”(sex==1)或者“women”(sex==0);
* 方法 void employeed():根据salary的值显示“no job”(salary==0)或者“ job”(salary!=0)。
*/
public class ManKind { int sex;
int salary; public void manOrWoman(){
if(sex == 0){
System.out.println("woman");
}else if(sex == 1){
System.out.println("man");
}
} public void employeed(){
if(salary != 0){
System.out.println("job");
}else{
System.out.println("no job");
}
} }

  

package com.uncleyong;

/**
* 定义类 Kids1 继承ManKind,并包括
* 成员变量 int yearsOld;
* 方法 printAge() 打印 yearsOld 的值。
*
* 在Kids1中重新定义employed() 方法,覆盖父类ManKind中定义的employed()方法,
* 输出“Kids should study and no job.”
*/
public class Kids1 extends ManKind { int yearsOld; void printAge(){
System.out.println("yearsOld: " + yearsOld);
} // 方法重写
public void employeed() {
System.out.println("Kids should study and no job.");
} //在Kids1类的main方法中实例化Kids1的对象 someKid,用该对象访问其父类的成员变量及方法。
public static void main(String[] args) {
Kids1 someKid = new Kids1();
someKid.sex = 1;
someKid.salary = 5000;
someKid.yearsOld = 25; someKid.manOrWoman();
someKid.employeed();
someKid.printAge();
}
}

super 关键字

super的功能

在Java类中使用super来引用父类的成分:

  super可用于访问父类中定义的属性
  super可用于调用父类中定义的成员方法(如下例子)
  super可用于在子类构造方法中调用父类的构造方法
  super的追溯不仅限于直接父类

例子:子类重写的方法中,调用父类中被重写的方法,需要用super

下面子类重写父类方法,会死循环(循环调用自己),导致栈溢出

package com.uncleyong;

public class Person {
private String country = "China"; public String getInfo(){
return "country:" + country;
}
}

  

public class Student extends Person{
private String school = "清华大学"; @Override
public String getInfo() {
return getInfo() + ", school:" + school; // 正确写法return this.getInfo() + ", school:" + school;
}
}

  

package com.uncleyong;

public class Test {
public static void main(String[] args) {
Student student = new Student();
student.getInfo();
}
}

  

构造方法不能继承

子类继承父类所有的成员变量和成员方法,但不继承父类的构造方法
在一个Java类中可以通过两种方式获得构造方法:
  使用系统默认的无参数构造方法
  显式定义一个或多个构造方法
一旦显式定义了构造方法,则系统不再提供默认构造方法

调用父类构造方法

在子类的构造方法中可使用super(参数列表)语句调用父类的构造方法;

如果子类的构造方法中没有显示地调用父类构造方法,也没有使用this关键字调用重载的其它构造方法(调用子类中重载子类的构造方法),则系统默认调用父类无参数的构造方法【可以在这个无参构造方法体中写内容,但是不能有参数】,见下方验证;

如果子类构造方法中既未显式调用父类构造方法,而父类中又没有无参的构造方法,则编译出错;

子类的构造方法中一定要用super方式调用父类的某一个构造方法,可以通过this间接方式调当前类的某一个构造方法(这个构造方法又通过super去调了父类的一个构造方法)
间接方式
子类构造方法中第一行this调用重载的构造方法,被调用的那个重载构造方法中第一行super调用父类构造方法
直接方式
子类构造方法中第一行直接super调用父类构造方法 父类只有有参构造
方案一:子类的构造方法中第一行用super调用父类有参构造方法
方案二:父类新增无参构造方法 父类中同时存在有参和无参构造方法:
子类的构造方法的第一行可以调用父类的有参构造方法,
也可以不调用(这样就默认调用父类无参构造方法):如果子类的构造方法中没有显示地调用父类构造方法,也没有使用this关键字调用重载的其它构造方法【调用子类中重载子类的构造方法】,则系统默认调用父类无参数的构造方法【可以在这个无参构造方法体中写内容,但是不能有参数】 super(…)和this(…)调用语句不能同时在一个构造函数中出现 super(…)或this(…)调用语句只能作为构造函数中的第一句出现

验证:子类调用父类构造函数

系统默认提供无参构造函数

public Animal(){
}

也可以自己在无参构造方法体中加内容,子类也可以调这个无参方法

public Animal(){
System.out.println("父类无参构造方法");
}

  

父类

public class Animal {
private String name;
private int age; public Animal(){
System.out.println("父类无参构造方法");
} // public Animal(String name){
// this.name = name;
// System.out.println("父类有参构造方法,形参name: " + name);
// } public String getInfor(){
return "name: " + name;
}
}

  

子类

public class Cat extends Animal {
private String sex; // public Cat(){
// super("tom");
// }
}

  

测试类

public class Test {
public static void main(String[] args) {
Cat cat = new Cat();
System.out.println(cat.getInfor());
}
}

结果

如果父类有参构造方法,那么,可以两个解决方案:

方案一:如果父类只有有参构造方法,需要在子类的构造方法的第一行调用父类的有参构造方法

父类

public class Animal {
private String name;
private int age; // public Animal(){
// System.out.println("父类无参构造方法");
// } public Animal(String name){
this.name = name;
System.out.println("父类有参构造方法,形参name: " + name);
} public String getInfor(){
return "name: " + name;
}
}

 

子类

public class Cat extends Animal {
private String sex; public Cat(){
super("tom");
}
}

  

测试类

public class Test {
public static void main(String[] args) {
Cat cat = new Cat();
System.out.println(cat.getInfor());
}
}

 

结果

方案二:父类中同时存在有参和无参构造方法,子类的构造方法的第一行可以调用父类的有参构造方法,也可以不调用(这样就默认调用父类无参构造方法)

如果子类的构造方法中没有显示地调用父类构造方法,也没有使用this关键字调用重载的其它构造方法【调用子类中重载子类的构造方法】,则系统默认调用父类无参数的构造方法【可以在这个无参构造方法体中写内容,但是不能有参数】

父类

public class Animal {
private String name;
private int age; public Animal(){
System.out.println("父类无参构造方法");
} public Animal(String name){
this.name = name;
System.out.println("父类有参构造方法,形参name: " + name);
} public String getInfor(){
return "name: " + name;
}
}

  

子类

public class Cat extends Animal {
private String sex; // public Cat(){
// super("tom");
// }
}

  

测试类

public class Test {
public static void main(String[] args) {
Cat cat = new Cat();
System.out.println(cat.getInfor());
}
}

  

子类对象实例化过程

示例

根据下图实现类。在TestCylinder类中创建Cylinder类的对象,设置圆柱的底面半径和高,并输出圆柱的体积,下面是uml图

父类

package com.uncleyong;

public class Circle {

    protected double radius;

    public Circle() {
this.radius = 1;
System.out.println("父类构造方法");
} public double getRadius() {
return radius;
} public void setRadius(double radius) {
this.radius = radius;
} public double findArea(){
return 3.14 * radius * radius;
} }

子类

package com.uncleyong;

public class Cylinder extends Circle{

    private double length;

    public Cylinder() {
this.length = 1;
} public double getLength() {
return length;
} public void setLength(double length) {
this.length = length;
} /**
* 返回圆柱的体积
* @return
*/
public double findVolume(){
return super.findArea() * length; // 这里要加super表示调父类的,不加super表示调本类中的findArea方法
} /**
* 返回圆柱的表面积
*/
@Override
public double findArea() {
return super.findArea() * 2 + 2 * 3.14 * radius * length;
} }

测试类

package com.uncleyong;

public class TestCylinder {

    public static void main(String[] args) {

        Cylinder cylinder = new Cylinder();

		cylinder.setLength(2);

        //返回表面积
System.out.println(cylinder.findArea());
//返回体积
System.out.println(cylinder.findVolume());
} }

多态性及其应用

多态性

在Java中,子类的对象可以替代父类的对象使用(父类类型的引用变量可以指向子类的对象)
一个变量只能有一种确定的数据类型
一个引用类型变量可能指向(引用)多种不同类型的对象

Person p = new Student();
Object o = new Person();//Object类型的变量o,指向Person类型的对象
o = new Student(); //Object类型的变量o,指向Student类型的对象

一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中新添加的属性和方法(子类有父类没有的属性和方法)

Student m = new Student();
m.school = “pku”; //合法,Student类有school成员变量
Person e = new Student();
e.school = “pku”; //非法,Person类没有school成员变量

属性是在编译时确定的,编译时e为Person类型,没有school成员变量,因而编译错误。

虚拟方法调用(Virtual Method Invocation)

正常的方法调用

Person e = new Person();
e.getInfo();
Student e = new Student();
e.getInfo();

虚拟方法调用(多态情况下)

Person e = new Student();
e.getInfo(); //调用Student类中重写的getInfo()方法

编译时类型和运行时类型:编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法。—— 动态绑定

在多态的情况下,调了父类的某个方法,但是这个方法被子类重写了,运行时,其实调的是子类重写的方法。【对象是子类的,所以调子类方法】

instanceof 操作符

如果下面p2要访问子类的属性和方法,需要把父类的实例变量p2强制转换为子类类型
Person p2 = new Man();
System.out.println(((Man) p2).school);
((Man) p2).work();
Woman w2 = (Woman)p2; // 强制转换成女人,编译的时候可以过,因为p2是人,运行的时候不能过,因为运行时发现p2是男人

x instanceof A:检验x(x指向的对象)是否为类A的对象,返回值为boolean型。
要求x所属的类(x这个句柄的类型)与类A必须是子类和父类的关系,否则编译错误。
如果x属于类A的子类B,x instanceof A值也为true。

使用 instanceof 运算符. 注意, 使用 instanceof 运算符, 必须要求前面的引用指向的变量和后边的类之间存在父子关系【前面<=后面就返回true】

总结:
instanceof前后必须有继承关系,不管哪个继承哪个,否则类型不兼容报错
如果前面继承后面,结果为true
如果前面等于后面,结果为true
如果后面继承前面,结果为false
总之,有继承关系时,前面<=后面,就返回true

示例:

        Boy b = new Boy();
System.out.println(">>>>>>>>>>>>>>>>");
// Boy继承了Student
// System.out.println(b instanceof Student); // true;如果Boy没有继承Student,报类型不兼容错误
// Boy2继承了Boy
System.out.println(b instanceof Boy2); // false,因为b不是Boy2的对象
System.out.println(b instanceof Boy); // true,因为b是Boy的对象
// Boy2继承了Boy
Boy2 b2 = new Boy2();
System.out.println(b2 instanceof Boy); // true,因为b2是Boy的对象

实例2

public class TestPerson {
public static void main(String[] args) {
//多态 //1. 创建一个 Man 的实例
Man m1 = new Man(); //2. 创建一个 Woman 的实例
Woman w1 = new Woman(); //3. 创建一个 Person 的实例
Person p1 = new Person();
/**
* 多态: 在Java中,父类的引用可以指向子类的对象.【子类的对象可以替代父类的对象使用】
* 1. 在多态情况下, 父类的实例变量不能再访问子类中新添加的属性和方法【来了一个人,是男是女都不知道,所以不能访问子类特有的属性和方法;如果下面p2要访问子类的属性和方法,需要把父类的实例变量p2强制转换为子类类型】
* 2. 方法的调用是在运行时确定的,所以调用的是 Man 类的 getInfo() 方法【在多态的情况下,调用了父类的方法,这个方法已经被子类重写,运行的时候,实际上调用的是子类已经重写的那个方法,对象是子类的,所以调子类方法】。―― 动态绑定(虚拟方法调用)
* 3. 在存在父子关系(多态)的情况下, 可以把父类的引用类型强制转换为子类的引用类型. 若实际上不能进行转换则
* 系统会抛出 java.lang.ClassCastException 类型转换异常.
* 4. 如何避免出现 java.lang.ClassCastException 异常呢? 在转换之前可以先判断一下对象实际上是否为指定的子类类型.
* 使用 instanceof 运算符. 注意, 使用 instanceof 运算符, 必须要求前面的引用指向的变量和后边的类之间存在父子关系
*/
//需要一个人, 但来的是一个男人! OK. 因为男人一定是一个人.
Person p2 = new Man();
System.out.println(((Man) p2).school); // 如果p2要访问子类的属性和方法(子类有父类没有的),需要把父类的实例变量p2强制转换为子类类型
((Man) p2).work();
System.out.println(p2.getInfo()); // Man's getInfo;按住ctrl点getInfo,跳转到Person类的getInfo,方法的调用是在运行时确定的,最终调用的是Man重写的的getInfo―― 动态绑定(虚拟方法法调用) //需要一个人, 但来的是一个女人! OK. 因为女人一定是一个人
Person p3 = new Woman(); //在多态情况下, 可以进行强制的类型转换
Man m2 = (Man) p2;
// Man m4 = (Man)p3; // 会抛出 java.lang.ClassCastException 异常 System.out.println(p3 instanceof Man); // false
System.out.println(p3 instanceof Woman); // true // System.out.println(m2 instanceof Woman); // Man和Woman无父子关系
System.out.println(m2 instanceof Man); // true
System.out.println(m2 instanceof Person); // true //需要一个男人, 但来的是个人! NO. 因为人不一定是男人.
//Man m2 = new Person(); //需要个男人, 但来的是一个女人。 NO!
//Man m3 = new Woamn(); }
}

  

针对上面第一条,如果下面p2要访问子类的属性和方法,需要把父类的实例变量p2强制转换为子类类型
Person p2 = new Man();
System.out.println(((Man) p2).school);
((Man) p2).work();
Woman w2 = (Woman)p2; // 强制转换成女人,编译的时候可以过,因为p2是人,运行的时候不能过,因为运行时发现p2是男人

对象类型转换 (Casting )

基本数据类型的Casting

小的数据类型可以自动转换成大的数据类型
  如long g=20; double d=12.0f
可以把大的数据类型强制转换(casting)成小的数据类型
  如 floate f=(float)12.0 int a=(int)1200L

对Java对象的强制类型转换称为造型

从子类到父类的类型转换可以自动进行
从父类到子类的类型转换必须通过造型(强制类型转换)实现
无继承关系的引用类型间的转换是非法的,编译报错
在造型前可以使用instanceof操作符测试一个对象的类型

从小到大(小东西放到大容器中),自动转
从大到小(大东西放到小容器中),强制转

示例

package com.uncleyong;

public class Person {
protected String name="person";
protected int age=50;
public String getInfo() {
return "Name: "+ name + "\n" +"age: "+ age;
}
}
class Student extends Person {
protected String school="pku";
public String getInfo() {
return "Name: "+ name + "\nage: "+ age
+ "\nschool: "+ school;
} }
class Graduate extends Student{
public String major="IT";
public String getInfo()
{
return "Name: "+ name + "\nage: "+ age
+ "\nschool: "+ school+"\nmajor:"+major;
}
}
package com.uncleyong;

public class TestInstance {

	/*
在类中定义方法method1(Person e);
在method1中:
(1)根据e的类型调用相应类的getInfo()方法。
(2)根据e的类型执行:
如果e为Person类的对象,输出:“a person”;
如果e为Student类的对象,输出
“a student”
“a person ”
如果e为Graduate类的对象,输出:
“a graduated student”
“a student”
“a person”
*/ public void method1(Person e){ // 多态的体现,Person类型的形参可以接收实际Person子类对象
String info = e.getInfo(); // 动态绑定
System.out.println(info); if(e instanceof Graduate){
System.out.println("a graduated student");
}
if(e instanceof Student){
System.out.println("a student");
}
if(e instanceof Person){
System.out.print("a person");
} System.out.println("\n"); } public static void main(String[] args) { TestInstance ti = new TestInstance(); Person p1 = new Person();
ti.method1(p1); Person p2 = new Student();
ti.method1(p2); Person p3 = new Graduate();
ti.method1(p3); } }  

Object 类及其主要方法

Object类

Object类是所有Java类的根父类

如果在类的声明中未使用extends关键字指明其父类,则默认父类为Object类

public class Person {
...
}
等价于:
public class Person extends Object {
...
}
例:

method(Object obj){…}  // 可以接收任何类作为其参数
Object o=new Person;
method(o);

==操作符与equals方法

==操作符

引用类型比较引用(是否指向同一个对象,即:是否指向同一块內存空間,要求 == 两边的类型必须一致或存在着父子关系, 否则编译出错;
  Person p1=new Person();

  Person p2=new Person();

  if (p1==p2){…}

基本类型比较值:

  int a=5; if(a==6){…}

  用"=="进行比较时,符号两边的数据类型必须一致(可自动转换的基本数据类型除外),否则编译出错;

equals()方法

equals()方法是Object类的方法,由于所有类都继承Object类,也就继承了equals()方法。

equals()只能比较引用类型,其作用与“==”相同,比较是否指向同一个对象(可以比较任意两个对象)。格式:obj1.equals(obj2)

可以在类中重写 equals 方法, 以达到定制比较两个对象内容是否相等的目的

特例:当用equals()方法进行比较时,对类File、String、Date及封装类(Wrapper Class)来说,是比较类型及内容而不考虑引用的是否是同一个对象;

原因:在这些类中,已经重写了equals()方法,可以通过 equals 方法來判定其內容是否相同

比较两个字符串的內容是否相同, 一定要使用 equals() 方法, 而不能使用 ==

toString 方法
1. Object 类定义的方法, 所以任何对象都可以来调用 toString() 方法
2. 默认情况下, toString() 方法 全类名@hash码
3. 可以根据需要重写 toString() 方法, 通常用于测试. 个别时候用于显示,增加可读性.
4. JDK 中的很多类都重写了 toString() 方法

toString()方法在Object类中定义,其返回值是String类型,返回值:类名和它的引用地址。

在进行String与其它类型数据的连接操作时,自动调用toString()方法

Date now=new Date();
System.out.println(“now=”+now); 相当于 System.out.println(“now=”+now.toString()); // now=Date@122345

可以根据需要在用户自定义类型中重写toString()方法,如String 类重写了toString()方法,返回字符串的值。

s1=“hello”;
System.out.println(s1); // 相当于System.out.println(s1.toString());【打印对象,会自动调对象的toString方法】
基本类型数据转换为String类型时,调用了对应封装类的 toString()方法,int a=10; System.out.println(“a=”+a);

示例:

父类

package com.uncleyong;

public class GeometricObject {
protected String color;
protected double weight;
}

子类

package com.uncleyong;

public class Circle1 extends GeometricObject{
private double radius; public double getRadius() {
return radius;
} public void setRadius(double radius) {
this.radius = radius;
} public Circle1() {
this.radius = 1;
this.weight = 1;
this.color = "white";
} public Circle1(double radius) {
this.radius = radius;
this.weight = 1;
this.color = "white";
} public Circle1(double radius, double weight, String color) {
this.radius = radius;
this.weight = weight;
this.color = color;
} public double findArea(){
return Math.PI * this.radius * this.radius;
} @Override
public boolean equals(Object obj) {
if(this == obj){
return true;
} if(obj == null){
return false;
} if(!(obj instanceof Circle1)){
return false;
} Circle1 c = (Circle1) obj; return c.getRadius() == this.radius;
} @Override
public String toString() {
return "" + this.radius; // 写为return this.radius;不行,因为radius是double
}
}

测试类

package com.uncleyong;

public class TestCircle1 {

    /**
* 写一个测试类,创建两个Circle对象,判断其颜色是否相等;
* 利用equals方法判断其半径是否相等;
* 利用toString()方法输出其半径。
*/
public static void main(String[] args) { Circle1 c1 = new Circle1(1, 2, "Black");
Circle1 c2 = new Circle1(2, 3, "Black");
Circle1 c3 = new Circle1(2, 2, "Black");
Circle1 c4 = new Circle1(2, 3, "Red"); // 比颜色
System.out.println(c1.color.equals(c2.color)); // true
// 比半径
System.out.println(c1.equals(c2)); // false // 比颜色
System.out.println(c3.color.equals(c4.color)); // false
// 比半径
System.out.println(c3.equals(c4)); // true System.out.println(c1); // 1.0 打印对象,会自动调对象的toString方法 }
}

封装类

针对八种基本定义相应的引用类型—封装类

int i = 10;
Integer j = 10; // Integer是封装类,基本数据类型10赋给j,自动装箱
自动装箱
Integer a = 128;

 

反编译生成的class文件:

Integer a = Integer.valueOf(128);

这就是基本数据类型的自动装箱,128是基本数据类型,然后被解析成Integer类。

注意:自动装箱规范要求 byte<= 127、char<=127、-128<=short <=127、-128<=int <=127都被包装到固定的对象中(缓存)。

自动拆箱

将 Integer 类表示的数据赋值给基本数据类型int,就执行了自动拆箱。

Integer a = new Integer(128);
int m = a;

反编译生成的class文件:

Integer a = new Integer(128);
int m = a.intValue();

自动装箱就是:Integer a = Integer.valueOf(int i);

自动拆箱就是:
  Integer a = new Integer(128);
  int m = a.intValue();

参考:https://www.cnblogs.com/uncleyong/p/9804074.html

练习题(参考答案已放在Q群文件中)

1、下面代码输出结果是?

父类

import java.util.Date;

public class Person {
private String name;
private int age;
private Date birthDate; public Person(String name, int age, Date d) {
this.name = name;
this.age = age;
this.birthDate = d;
}
public Person(String name, int age) {
this(name, age, null); // 调用同一个类中的重载构造方法,三个参数的
}
public Person(String name, Date d) {
this(name, 30, d); // 调用同一个类中的重载构造方法,三个参数的
}
public Person(String name) {
this(name, 30); // 调用同一个类中的重载构造方法,两个参数的
}
public Person() {
System.out.println("父类无参构造方法");
}
}

子类

public class Student extends Person {
private String school;
public Student(String name, int age, String school) {
super(name, age);
this.school = school;
}
public Student(String name, String school) {
super(name);
this.school = school;
}
public Student(String school) {
this.school = school;
} public static void main(String[] args) {
Student student = new Student("清华大学");
System.out.println(student.school);
}
}

2、定义MyDate类,在MyDate类中覆盖equals方法,使其判断当两个MyDate类型对象的年月日都相同是,结果为ture,否则为false。

TestEquals.java

Java【第七篇】面向对象之类设计的更多相关文章

  1. java 第七章 面向对象高级特性

    一.类的继承 (一)继承的含义 1.在Java中定义一个类时,让该类通过关键字extends继承一个已有的类,这就是类的继承(泛化). 2.被继承的类称为父类(超类,基类),新的类称为子类(派生类). ...

  2. java 28 - 1 设计模式 之 面向对象思想设计原则和模版设计模式概述

    在之前的java 23 中,了解过设计模式的单例模式和工厂模式.在这里,介绍下设计模式 面向对象思想设计原则 在实际的开发中,我们要想更深入的了解面向对象思想,就必须熟悉前人总结过的面向对象的思想的设 ...

  3. 第七篇 :微信公众平台开发实战Java版之如何获取微信用户基本信息

    在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的.对于不同公众号,同一用户的openid不同). 公众号可通过本接口来根据O ...

  4. Python开发【第七篇】:面向对象 和 python面向对象进阶篇(下)

    Python开发[第七篇]:面向对象   详见:<Python之路[第五篇]:面向对象及相关> python 面向对象(进阶篇)   上一篇<Python 面向对象(初级篇)> ...

  5. Java面向对象课程设计——购物车

    Java面向对象课程设计——购物车 小组成员:余景胜.刘格铭.陈国雄.达瓦次仁 一.前期调查 流程 客人(Buyer)先在商城(Mall)中浏览商品(Commidity),将浏览的商品加入购物车(Sh ...

  6. PHP 进阶篇:面向对象的设计原则,自动加载类,类型提示,traits,命名空间,spl的使用,反射的使用,php常用设计模式 (麦子学员 第三阶段)

    以下是进阶篇的内容:面向对象的设计原则,自动加载类,类型提示,traits,命名空间,spl的使用,反射的使用,php常用设计模式 ================================== ...

  7. java并发编程工具类JUC第七篇:BlockingDeque双端阻塞队列

    在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue.LinkedBlockingQueue.Priorit ...

  8. Python开发【第七篇】:面向对象

    Python之路[第五篇]:面向对象及相关   面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...

  9. 【Python之路】第七篇--Python基础之面向对象及相关

    面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查obj是否是类 cls 的对象 class Foo(objec ...

  10. GOF 的23种JAVA常用设计模式总结 03 面向对象七大设计原则

    在软件开发中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据 7 条原则来开发程序,从而提高软件开发效率.节约软件开发成本和维护成本. 各位代码界的大佬们总结出的七 ...

随机推荐

  1. 关于Windows系统不会变慢的设想

    记录软件安装的过程,比如创建了哪些服务,哪些计划任务以及启动项等等. 然后软件安装完成后把关于软件的进程,服务,计划任务等都删掉. 然后手动创建一个脚本,用脚本代替软件的启动.比如,如果要启动sqls ...

  2. Nodejs 操作 Sql Server

    Nodejs 操作 Sql Server Intro 最近项目需要爬取一些数据,数据有加密,前端的js又被混淆了,ajax请求被 hook 了,有些复杂,最后打算使用 puppeteer 来爬取数据. ...

  3. DVWA 黑客攻防演练(七)Weak Session IDs

    用户访问服务器的时候,一般服务器都会分配一个身份证 session id 给用户,用于标识.用户拿到 session id 后就会保存到 cookies 上,之后只要拿着 cookies 再访问服务器 ...

  4. SQLServer之修改标量值函数

    修改标量值函数注意事项 更改先前通过执行 CREATE FUNCTION 语句创建的现有 Transact-SQL 或 CLR 函数,但不更改权限,也不影响任何相关的函数.存储过程或触发器. 不能用 ...

  5. 关于swagger——WebApi一个controller中出现多个Get是出现错误的处理

    如 /// <summary> /// 测试处理 /// </summary> public class TestController : ApiController { // ...

  6. web 项目运用通用的xml配置

    jdk10的转换: <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncod ...

  7. DP思想笔记

    一.思想 DP也是把复杂的问题分解为许多子问题,与分治法不同的是,分治法的各个子问题互相之间没有联系,而动态规划却有.前一个子问题的结果与下一步的子问题的结果是什么有关系.这就决定了DP算法肯定有一个 ...

  8. MySQL 数据表创建及管理

    use stuinfo; -- 指定当前数据库 CREATE table if not exists student1( -- 创建数据表student1 sNo ) not NULL, sName ...

  9. 基于udp简单聊天的系统

    老师博客:http://www.cnblogs.com/Eva-J/articles/8244551.html#_label4 基于udp的简单的聊天代码 说明:这段代码,显示有client向serv ...

  10. JavaScript—面向对象开发详解和垃圾回收

    面向对象的概述 ECMAScript 有两种开发模式:1.函数式(过程化),2.面向对象(OOP). 面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象.但是, ...