-
继承性的练习
-
Eclipse的Debug功能
-
方法重写
-
测试四种权限修饰符
-
super关键字
-
子类对象实例化过程
-
继承和super的练习
-
多态
-
虚拟方法调用的再理解
1,继承性的练习
package com.atguigu.java;
public class ManKind {
private int sex;
private int salary;
public ManKind() {
}
public ManKind(int sex, int salary) {
this.sex = sex;
this.salary = salary;
}
public void manOrWoman() {
if(sex == 1) {
System.out.println("man");
}else if(sex == 0) {
System.out.println("woman");
}
}
public void employeed() {
String jobInfo = (salary == 0) ? "no job" : "job";
System.out.println(jobInfo);
}
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;
}
}
package com.atguigu.java;
public class Kids extends ManKind {
private int yearsOld;
public Kids() {
}
public Kids(int yearsOld) {
this.yearsOld = yearsOld;
}
public void printAge() {
System.out.println("I am " + yearsOld + "year old");
}
public int getYearsOld() {
return yearsOld;
}
public void setYearsOld(int yearsOld) {
this.yearsOld = yearsOld;
}
}
package com.atguigu.java;
public class KidsTest {
public static void main(String[] args) {
Kids someKid = new Kids(12);
someKid.printAge();
someKid.setSalary(0);
someKid.setSex(1);
someKid.employeed();
someKid.manOrWoman();
}
}
package com.atguigu.java;
public class Circle {
private double radius;
public Circle() {
radius = 1.0;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public double findArea() {
return Math.PI * radius * radius;
}
}
package com.atguigu.java;
public class Cylinder extends Circle {
private double length;
public Cylinder() {
length = 1.0;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double findVolume() {
return findArea() * getLength();
}
}
package com.atguigu.java;
public class CylinderTest {
public static void main(String[] args) {
Cylinder cy = new Cylinder();
cy.setRadius(2.1);
cy.setLength(3.4);
double volume = cy.findVolume();
System.out.println("圆柱体积为:" + volume);
double area = cy.findArea();
System.out.println("底面积为:" + area);
}
}
2,Eclipse的Debug功能
3,方法重写
package com.atguigu.java;
public class Person {
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() { // 被子类重写的方法
System.out.println("吃饭");
}
public void walk(int distance) {
System.out.println("走了" + distance + "公里");
show();
eat();
}
private void show() {
System.out.println("我是一个人");
}
public Object info() {
return null;
}
public double info1() {
return 1.0;
}
}
package com.atguigu.java;
public class Student extends Person {
String major;
public Student() {
}
public Student(String major) {
this.major = major;
}
public void study() {
System.out.println("学习,专业是:" + major);
}
public void eat() { // 重写父类中的eat()方法
System.out.println("学生应该多吃有营养的");
}
public void show() { // Eclipse中也没有重写方法提示(倒三角形),这不是一个重写方法,是子类自己定义的方法
System.out.println("我是一个学生");
}
public String info() { // 返回一个Object的子类,构成重写
return null;
}
// public int info1() { // 报错,父类的该方法在子类中可见,一个同名方法没有构成重载和重写
// return 1;
// }
public double into1() {
return 2.0;
}
}
package com.atguigu.java;
/*
* 方法声明:
* 权限修饰符 返回值类型 方法名(形参列表) throws 异常类型 {
* // 方法体
* }
* 重写的规定:
* 子类重写的方法要与父类被重写方法的方法名和参数列表相同(方法名和参数列表确定唯一方法)
* 子类重写方法的权限修饰符不小于父类被重写方法;父类中private的方法对于子类是不可见的,
* 所以子类不能重写父类中声明为private的方法
* 若父类被重写方法的返回值类型是void,则子类重写方法的返回值类型也是void
* 若父类被重写方法返回A类型,则子类重写方法返回可以是A也可以是A的子类
* 显然,若父类被重写方法返回基本数据类型,则子类重写方法返回相同的基本数据类型
* 子类重写方法抛出的异常不能大于父类被重写方法抛出的异常类型
*
* static的方法不能被重写。当子父类中有同名同参的方法时,要么都声明为非static(在满足以上条件时
* 就是重写),要么都声明为static(不是重写)
* 在实际开发中,要重写方法时,直接将父类中被重写方法的定义复制到子类中,重写方法体即可
*/
public class PersonTest {
public static void main(String[] args) {
Student s = new Student("计科");
s.eat();
s.show(); // 父类的show()对于子类是不可见的,子类中的show()只是子类自己定义的,并不是重写的父类方法
s.walk(10); // 子类中没有walk()方法,所以调用的是继承自父类中的,在父类中walk()又调用了父类自己的
// show()和eat(),因为权限导致show()没有被重写,所以执行的是父类的show()、子类的eat()
s.study();
System.out.println("***********");
Person p1 = new Person();
p1.eat();
}
}
4,测试四种权限修饰符
package com.atguigu.java1;
public class Order {
private int orderPrivate;
int orderDefault;
protected int orderProtected;
public int orderPublic;
private void methodPrivate() {
orderPrivate = 1;
orderDefault = 2;
orderProtected = 3;
orderPublic = 4;
}
void methodDefault() {
orderPrivate = 1;
orderDefault = 2;
orderProtected = 3;
orderPublic = 4;
}
protected void methodProtected() {
orderPrivate = 1;
orderDefault = 2;
orderProtected = 3;
orderPublic = 4;
}
public void methodPublic() {
orderPrivate = 1;
orderDefault = 2;
orderProtected = 3;
orderPublic = 4;
}
}
package com.atguigu.java11;
import com.atguigu.java1.Order;
public class SubOrder extends Order {
// 定义在不同包下的子类
// 这里是定义属性的地方,可以声明属性并赋值,但不能这样
// int i;
// i = 1;
// 所以不能在这直接测试orderPublic = 1;
public void method() {
orderProtected = 1; // 在不同包下的子类,protected的权限是可见的
orderPublic = 2;
// orderDefault = 1;
// orderPrivate = 2; 不可见
}
}
5,super关键字
package com.atguigu.java1;
public class Person {
String name;
int age;
int id = 1001; // 身份证号
public Person() {
System.out.println("我无处不在");
}
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this(name);
this.age = age;
}
public void eat() {
System.out.println("人吃饭");
}
public void walk() {
System.out.println("人走路");
}
}
package com.atguigu.java1;
/*
* super理解为父类
* 可以用来调用属性、方法、构造器
* 调用属性和方法:
* 在子类的方法或构造器中可以通过super.属性或super.方法的方式显示调用父类中的结构,
* 通常情况下省略super
* 当子父类中有同名的属性或方法时,通过super表明调用的就是父类中的结构
* 调用构造器:
* 在子类构造器中显示使用super(形参列表)来调用父类构造器
* super(形参列表)必须声明在子类构造器中的首行
* 由于调用本类构造器的this(形参列表)也必须放在首行,所以二者只能二选一
* 在子类构造器中如果既没有写this(形参列表)也没有super(形参列表),则默认调用父类的
* 空参构造器super()。注意如果父类中写了带参的构造器而没有写空参构造器,此时是不会默认
* 提供空参构造器的,所以在子类构造器中如果没有显示写出调用父类的带参构造器则会报错
* 构造器的第一行不是super调用父类构造器就是this调用本来构造器;若一个类有多个构造器,则至少有
* 一个调用了父类构造器,其他的则是通过this调用本类构造器,如果都调用this则会形成循环
* 父类的构造器一定会被子类调用,Object是所有类的父类,它的构造器也一定会被子类调用;因为有了
* 这样的机制,就保证了父类的结构会被加载到子类中
*/
public class Student extends Person {
String major;
int id = 1002; // 学号,开发中不会这样写。当创建当前对象时,堆空间中有两个id
public Student() {
// super(); // 没有显示的写出,其实默认也调用了父类的空参构造器
}
public Student(String major) {
// super();
this.major = major;
}
public Student(String name, int age, String major) {
// this.name = name; // 在父类没有将属性声明为private时可以这样做
// this.age = age; // 如果声明为private,也可以通过set()方法来设置,但一般不这样做
super(name, age); // 调用父类构造器给属性赋值
this.major = major;
}
public void eat() {
System.out.println("学生多吃有营养的");
}
public void study() {
System.out.println("学生学习知识");
eat(); // 调用子类重写方法
super.eat(); // 调用父类的被重写方法
walk(); // this.walk(),先在本类中找,没找到就去父类中找,这里的父类可以是向上继承的所有父类。若是写成super.walk()则直接去父类中找
}
public void show() {
System.out.println("name = " + this.name + "age = " + super.age); // 此时属性没有冲突,Student有自己的name和age属性,既可以说调用自己的,也可以调用父类的
System.out.println("id = " + id); // 当子父类中都有时,默认调用子类自己的,相当于this.id
System.out.println("id = " + super.id); // 调用父类的属性
// 当使用this.属性时,明确指出先在当前子类中查找,有的话就用子类的,没有的话还是要去父类中找;而super.属性则是直接跳过子类,直接去父类中找
}
}
6,子类对象实例化过程
7,继承和super的练习
package com.atguigu.java2;
public class Account {
private int id;
private double balance;
private double annualInterestRate;
public Account(int id, double balance, double annualInterestRate) {
super();
this.id = id;
this.balance = balance;
this.annualInterestRate = annualInterestRate;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public double getAnnualInterestRate() {
return annualInterestRate;
}
public void setAnnualInterestRate(double annualInterestRate) {
this.annualInterestRate = annualInterestRate;
}
public double getMonthlyInterest() {
return annualInterestRate / 12;
}
public void withdraw(double amount) {
if(balance >= amount) {
balance -= amount;
return;
}
System.out.println("余额不足");
}
public void deposit(double amount) {
if(amount > 0) {
balance += amount;
}
}
}
package com.atguigu.java2;
public class CheckAccount extends Account {
private double overdraft; // 可透支限额
public CheckAccount(int id, double balance, double annualInterestRate, double overdraft) {
super(id, balance, annualInterestRate);
this.overdraft = overdraft;
}
public void withdraw(double amount) {
if(getBalance() >= amount) {
super.withdraw(amount);
}else if(overdraft >= amount - getBalance()) {
overdraft -= (amount - getBalance());
super.withdraw(getBalance());
}else {
System.out.println("超出透支额度");
}
}
}
8,多态
package com.atguigu.java3;
public class Person {
String name;
int age;
public void eat() {
System.out.println("人:吃饭");
}
public void walk() {
System.out.println("人:走路");
}
}
package com.atguigu.java3;
public class Man extends Person {
boolean isSmoking;
public void earnMoney() {
System.out.println("男人负责挣钱养家");
}
public void eat() {
System.out.println("多吃肉");
}
public void walk() {
System.out.println("潇洒地走路");
}
}
package com.atguigu.java3;
public class Woman extends Person {
boolean isBeauty;
public void goShopping() {
System.out.println("女人喜欢购物");
}
public void eat() {
System.out.println("减肥");
}
public void walk() {
System.out.println("妖娆地走路");
}
}
package com.atguigu.java3;
/*
* 多态性:父类引用指向子类对象
* 使用:虚拟方法调用
* 在编译期间,只能调用父类中声明的方法,而在运行期间,实际调用的是子类中重写的方法
* 编译看左边(引用类型),运行看右边(对象实际类型)
* 使用前提:
* 要有类的继承关系;子类中重写了父类方法
*/
public class PersonTest {
public static void main(String[] args) {
Person p1 = new Person();
p1.eat();
Man man = new Man();
man.eat();
man.age = 25;
man.earnMoney();
Person p2 = new Man(); // 对象的多态性:父类的引用指向子类的对象
p2.eat(); // 调用的是子类中重写过的方法——虚拟方法调用。编译时发现Person类型有eat()方法,所以不报错,运行时发现eat()方法被重写了,所以执行的是Man重写的方法
// p2.earnMoney(); // 编译不通过,Person类型中没有这个方法
Person p3 = new Woman();
p3.eat(); // 调用的是子类Woman重写的方法
}
}
package com.atguigu.java3;
public class AnimalTest {
public static void main(String[] args) {
AnimalTest test = new AnimalTest();
test.func(new Dog()); // 给一个animal的引用赋值一个Dog对象的引用,当调用eat()时,
// 编译发现animal有这个方法,通过,执行时发现这其实是一个Dog
// 的对象,所以执行Dog的eat()方法
}
public void func(Animal animal) {
animal.eat();
animal.shout();
}
// public void func(Dog dog) { // 有了多态性后,就不用写以下的重载方法了
// dog.eat();
// dog.shout();
// }
// public void func(Cat cat) {
// cat.eat();
// cat.shout();
// }
}
class Animal {
public void eat() {
System.out.println("动物:进食");
}
public void shout() {
System.out.println("动物:叫");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("狗吃骨头");
}
public void shout() {
System.out.println("汪汪汪");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
public void shout() {
System.out.println("喵喵喵");
}
}
package com.atguigu.java3;
import java.sql.Connection;
public class SqlTest {
public void doData(Connection conn) { // 可以传入new MySQLConnection();或是new OracleConnection();的对象
// 规范的步骤去操作数据,不管传入的是哪个子类对象,子类中都重写了以下的方法
// conn.method1();
// conn.method2();
// conn.method3();
}
}
package com.atguigu.java3;
public class Test {
public static void main(String[] args) {
Test1 t = new Test2();
System.out.println(t.id); // 1001,此时编译运行都看左边,调用的是Test1类型的属性
}
}
class Test1 {
int id = 1001;
}
class Test2 extends Test1 {
int id = 1002;
}
9,虚拟方法调用的再理解
package com.atguigu.java2;
import java.util.Random;
public class InterviewTest {
public static Animal getInstance(int key) {
switch(key) {
case 0:
return new Cat();
case 1:
return new Dog();
default:
return new Sheep();
}
}
public static void main(String[] args) {
int key = new Random().nextInt(3);
System.out.println(key);
Animal animal = getInstance(key); // key是一个随机数,在编译期时无法知道创建的是哪个对象,只有在运行时确定
animal.eat();
}
}
class Animal {
protected void eat() {
System.out.println("animal eat food");
}
}
class Cat extends Animal {
protected void eat() {
System.out.println("cat eat fish");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("Dog eat bone");
}
}
class Sheep extends Animal {
public void eat() {
System.out.println("sheep eat grass");
}
}