练习
2. (1)定义一个ManKind类,包括
成员变量int sex和int salary;
方法void manOrWoman():根据sex的值显示“man”(sex==1)或者“woman”(sex==0);
方法void employeed():根据salary的值显示“no job”(salary==0)或者“ job”(salary!=0)。
(2)定义类Kids继承ManKind,并包括
成员变量int yearsOld;
方法printAge()打印yearsOld的值。
(3)定义类KidsTest,在类的main方法中实例化Kids的对象someKid,用该对象访问其父类 的成员变量及方法。
- package com.xxx.exer;
-
- 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 {
- System.out.println("woman");
- }
- }
-
- 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 employeed() {
- if(salary == 0) {
- System.out.println("no job");
- }else {
- System.out.println("job");
- }
- }
-
- }
-
- package com.xxx.exer;
-
- public class Kids extends ManKind{
- private int yearsOld;
-
-
-
- public Kids() {
-
- }
-
-
-
- public Kids(int yearsOld) {
- this.yearsOld = yearsOld;
- }
-
-
-
- public int getYearsOld() {
- return yearsOld;
- }
-
-
-
- public void setYearsOld(int yearsOld) {
- this.yearsOld = yearsOld;
- }
-
-
-
- public void printAge() {
- System.out.println("I am " + yearsOld + " years old.");
- }
- }
- package com.xxx.exer;
-
- 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();
- }
- }
3. 根据下图实现类。在CylinderTest类中创建Cylinder类的对象,设置圆 柱的底面半径和高,并输出圆柱的体积。
- package com.xxx.exer1;
-
- 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.xxx.exer1;
-
- 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() * length;
- }
- }
- package com.xxx.exer1;
-
- public class CylinderTest {
- public static void main(String[] args) {
- Cylinder cy = new Cylinder();
-
- cy.setRadius(2.1);
- cy.setLength(3.4);
- System.out.println("圆柱的体积为:" + cy.findVolume());
- System.out.println("圆柱的底面积为:" + cy.findArea());
- }
- }
测试问题代码
- package com.xxx.java;
-
-
- public class DebugTest {
- public static void main(String[] args) {
- int i = 10;
- int j = 20;
- System.out.println("i = " + i + ", j = " + j);
-
- DebugTest test = new DebugTest();
- int max = test.getMax(i, j);
-
- System.out.println("max = " + max);
- }
-
- private int getMax(int k, int m) {
- int max = 0;
- if (k < m) {
- max = k;
- } else {
- max = m;
- }
- return max;
- }
-
- }
代码没报错,但结果不对
- package com.xxx.java;
-
-
- public class DebugTest1 {
-
- public static void main(String[] args) {
- int[] arr = new int[] {1,2,3,4,5};
- System.out.println(arr);
-
- char[] arr1 = new char[] {'a','b','c'};
- System.out.println(arr1);
- }
-
- }
打印char数组输出字符串,而不是地址值
debug界面
双击代码行首位置添加断点(若断点不生效可以按ctrl+alt+b)
第一个图标resume 恢复:执行完当前行所在断点的所有代码,进入下一个断点,如果没有就结束
第三个图标Terminate:强行终止
第五个图标step into跳入(F5):进入当前行所调用的方法中
第六个图标step over(F6):执行完当前行的语句,进入下一行
第七个图标step return跳回(F7):执行完当前行所在的方法,进入下一行
第八个图标drop to frame:回到当前行所在的方法的第一行
debug后记得切换回javaee视图
定义:在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置、覆盖。 在程序执行时,子类的方法将覆盖父类的方法。
要求:
1. 子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
2. 子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型
如:父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
父类被重写的方法的返回值类型是A类,则子类重写的方法的返回值类型可以是A 类或A类的子类
父类被重写的方法的返回值类型是基本数据类型,则子类重写的方法的返回值类 型必须是相同的基本数据类型
3. 子类重写的方法使用的访问权限(权限修饰符)不能小于父类被重写的方法的访问权限
且子类不能重写父类中声明为private权限的方法
4. 子类方法抛出的异常类型不能大于父类被重写方法的异常类型
注意:
子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为static 的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法。
- package com.xxx.java1;
-
- public class Person {
- String name;
- int age;
-
- public Person() {
-
- }
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- static 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 0.0;
- }
- }
- package com.xxx.java1;
-
- public class Student extends Person {
- String major;
-
- public Student() {
-
- }
-
- public Student(String major) {
- this.major = major;
- }
-
- public void study() {
- System.out.println("学习,专业是:" + major);
- }
-
- public static void eat() {
- System.out.println("学生多吃有营养的食物");
- }
-
- public void show() {
- System.out.println("我是一个学生");
- }
-
- public String info() {
- return null;
- }
-
- //public int info1() {
- // return 0;
- //}
- }
- package com.xxx.java1;
-
- public class PersonTest {
- public static void main(String[] args) {
- Student s = new Student("计算机科学与技术");
- s.eat();
- s.walk(10);
- s.study();
- }
- }
1.如果现在父类的一个方法定义成private访问权限,在子类中将此方法声明为default访问权限,那么这样还叫重写吗?(NO)
2. 修改练习1.2中定义的类Kids,在Kids中重新定义employeed()方法,覆盖父类ManKind中定义的employeed()方法,输出“Kids should study and no job.”
- package com.xxx.exer;
-
- public class Kids extends ManKind{
- private int yearsOld;
-
-
-
- public Kids() {
-
- }
-
-
-
- public Kids(int yearsOld) {
- this.yearsOld = yearsOld;
- }
-
-
-
- public int getYearsOld() {
- return yearsOld;
- }
-
-
-
- public void setYearsOld(int yearsOld) {
- this.yearsOld = yearsOld;
- }
-
-
-
- public void printAge() {
- System.out.println("I am " + yearsOld + " years old.");
- }
-
- public void employeed() {
- System.out.println("Kids should study and no job.");
- }
- }
权限修饰符Protected
创建class时指定父类
选择browse
搜索并选择父类
完成
- package com.xxx.java2;
-
- 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() {
-
- }
-
- protected void methodProtected() {
-
- }
-
- public void methodPublic() {
-
- }
- }
- package com.xxx.java2;
-
- public class OrderTest {
- public static void main(String[] args) {
- Order order = new Order();
-
- order.orderDefault = 1;
- order.orderProtected = 2;
- order.orderPublic = 3;
-
- order.methodDefault();
- order.methodProtected();
- order.methodPublic();
-
- //在不同类无法使用private
- //order.orderPrivate = 0;
- //order.methodPrivate();
- }
- }
- package com.xxx.java3;
-
- import com.xxx.java2.Order;
-
- public class SubOrder extends Order {
- public void method() {
- orderProtected = 2;
- orderPublic = 3;
-
- methodProtected();
- methodPublic();
-
- //在不同包的子类中无法使用private和缺省
- //orderPrivate = 0;
- //orderDefault = 1;
-
- //methodPrivate();
- //methodDefault();
- }
-
- }
- package com.xxx.java3;
-
- import com.xxx.java2.Order;
-
- public class OrderTest {
- public static void main(String[] args) {
- Order order = new Order();
-
- order.orderPublic = 3;
- order.methodPublic();
-
- // 在不同包中,且不是子类无法使用private、缺省、protected
- // order.orderPrivate = 0;
- // order.orderDefault = 1;
- // order.orderProtected = 2;
-
- // order.methodPrivate();
- // order.methodDefault();
- // order.methodProtected();
- }
- }
在Java类中使用super来调用父类中的指定操作:
super可用于访问父类中定义的属性
super可用于调用父类中定义的成员方法
super可用于在子类构造器中调用父类的构造器
注意:
尤其当子父类出现同名成员时,可以用super表明调用的是父类中的成员
super的追溯不仅限于直接父类
super和this的用法相像,this代表本类对象的引用,super代表父类的内存 空间的标识
子类中所有的构造器默认都会访问父类中空参数的构造器
当父类中没有空参数的构造器时,子类的构造器必须通过this(参数列表)或者super(参数列表)语句指定调用本类或者父类中相应的构造器。同时,只能”二选一” ,且必须放在构造器的首行
如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译出错
当在构造器首行既没有调用this(形参列表)也没有调用super(形参列表)默认调用super();
- package com.xxx.java3;
-
- 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 = name;
- this.age = age;
- }
-
- public void eat() {
- System.out.println("人吃饭");
- }
-
- public void walk() {
- System.out.println("人走路");
- }
- }
- package com.xxx.java3;
-
- public class Student extends Person {
-
- String major;
- int id = 1002;
-
- public Student() {
- super(); //默认调用
- }
-
- public Student(String major) {
- super();
- this.major = major;
- }
-
-
- public Student(String name, int age,String major) {
- super(name,age);
- this.major = major;
- }
-
- public void eat() {
- System.out.println("学生,多吃有营养的事物");
- }
-
- public void study() {
- System.out.println("学生,学习知识");
- this.eat();
- super.eat();
- }
-
- public void show() {
- System.out.println("name = " + this.name + " age = " + super.age);
- System.out.println("id = " + this.id);
- System.out.println("id = " + super.id);
- }
- }
- package com.xxx.java3;
-
- public class SuperTest {
- public static void main(String[] args) {
- Student s = new Student();
-
- s.show();
-
- System.out.println();
-
- s.study();
-
- Student s1 = new Student("Tom",21,"IT");
- s1.show();
-
- Student s2 = new Student();
- }
- }
当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器直到调用了java,lang,object类中空参的构造器为止。正因为加载过所有的父类的结构,所以才可以看到内存中有父类中的结构,子类对象才可以考虑进行调用。
1、写一个名为 Account 的类模拟账户。该类的属性和方法如下图所示。该类包括的属性: 账号 id,余额 balance,年利率 annualInterestRate;包含的方法:访问器方法(getter 和 setter 方法),返回月利率的方法 getMonthlyInterest(),取款方法 withdraw(),存款方法 deposit()。
写一个用户程序测试 Account 类。在用户程序中,创建一个账号为 1122、余额为 20000、 年利率 4.5%的 Account 对象。使用 withdraw 方法提款 30000 元,并打印余额。 再使用 withdraw 方法提款 2500 元,使用 deposit 方法存款 3000 元,然后打印余额和月利率。
- package com.xxx.exer2;
-
- 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;
- }
- }
-
-
-
- }
2、创建 Account 类的一个子类 CheckAccount 代表可透支的账户,该账户中定义一个属性 overdraft 代表可透支限额。在 CheckAccount 类中重写 withdraw 方法,其算法如下:
如果(取款金额<账户余额),
可直接取款
如果(取款金额>账户余额),
计算需要透支的额度
判断可透支额 overdraft 是否足够支付本次透支需要,如果可以
将账户余额修改为 0,冲减可透支金额
如果不可以
提示用户超过可透支额的限额
要求:写一个用户程序测试 CheckAccount 类。在用户程序中,创建一个账号为 1122、余 额为 20000、年利率 4.5%,可透支限额为 5000 元的 CheckAccount 对象。 使用 withdraw 方法提款 5000 元,并打印账户余额和可透支额。 再使用 withdraw 方法提款 18000 元,并打印账户余额和可透支额。 再使用 withdraw 方法提款 3000 元,并打印账户余额和可透支额。
提示:
(1) 子类 CheckAccount 的构造方法需要将从父类继承的 3 个属性和子类自己的属性全 部初始化。
(2) 父类Account的属性balance被设置为private,但在子类CheckAccount的withdraw 方 法中需要修改它的值,因此应修改父类的 balance 属性,定义其为 protected。
运行结果如下图所示
- package com.xxx.exer2;
-
- public class AccountTest {
- public static void main(String[] args) {
- Account acct = new Account(1122,20000,0.045);
-
- acct.withdraw(30000);
- System.out.println("余额为:" + acct.getBalance());
-
- acct.withdraw(2500);
- System.out.println("余额为:" + acct.getBalance());
-
- acct.deposit(3000);
- System.out.println("余额为:" + acct.getBalance());
-
- System.out.println("月利率为:" + acct.getMonthlyInterest());
- System.out.println("***************************");
-
- CheckAccount c = new CheckAccount(1122,20000,0.045,5000);
-
- c.withdraw(5000);
- System.out.println("余额为:" + c.getBalance());
- System.out.println("可透支额度为:" + c.getOverdraft());
-
- c.withdraw(18000);
- System.out.println("余额为:" + c.getBalance());
- System.out.println("可透支额度为:" + c.getOverdraft());
-
- c.withdraw(3000);
- System.out.println("余额为:" + c.getBalance());
- System.out.println("可透支额度为:" + c.getOverdraft());
- }
- }
- package com.xxx.exer2;
-
- 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 double getOverdraft() {
- return overdraft;
- }
-
-
- public void setOverdraft(double overdraft) {
- this.overdraft = overdraft;
- }
-
-
- @Override
- 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("超过可透支额度");
- }
- }
- }
多态性,是面向对象中最重要的概念,在Java中的体现:
对象的多态性:父类的引用指向子类的对象
可以直接应用在抽象类和接口上
Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。简称:编译时,看左边;运行时,看右边。
若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)
多态情况下, “看左边” :看的是父类的引用(父类中不具备子类特有的方法)
“看右边” :看的是子类的对象(实际运行的是子类重写父类的方法)
注意:
调用子类重写的方法称为——虚拟方法调用
只能调用子类重写的方法,不能调用子类特有的方法
对象的多态性只适用于方法,不适用于属性
子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。
- package com.xxx.java4;
-
- public class Person {
- String name;
- int age;
- int id = 1001;
-
- public void eat() {
- System.out.println("人吃饭");
- }
-
- public void walk() {
- System.out.println("人走路");
- }
- }
- package com.xxx.java4;
-
- public class Man extends Person {
- boolean isSomking;
- int id = 1002;
-
- public void earnMoney() {
- System.out.println("男人负责挣钱养家");
- }
-
- public void eat() {
- System.out.println("男人多吃肉");
- }
-
- public void walk() {
- System.out.println("男人走路");
- }
- }
- package com.xxx.java4;
-
- 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.xxx.java4;
-
- public class PersonTest {
- public static void main(String[] args) {
- Person p = new Person();
- p.eat();
-
- Man m = new Man();
- m.eat();
- m.age = 25;
- m.earnMoney();
-
- System.out.println("*******************");
- //多态性
- Person p1 = new Man();
-
- Person p2 = new Woman();
-
- p1.eat(); //执行子类重写的方法
- p1.walk();
- System.out.println(p1.id);
-
- //p1.earnMoney();
- }
- }
- package com.xxx.java4;
-
- import java.sql.Connection;
-
- public class AnimalTest {
-
- public static void main(String[] args) {
- AnimalTest a = new AnimalTest();
-
- a.func(new Dog());
- a.func(new Cat());
- }
-
- public void func(Animal animal) {
- animal.eat();
- animal.shout();
- }
-
- //如果没有多态性,则想执行main中的代码还得再创建两个方法
- // 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("猫叫");
- }
- }
-
- //举例二
- //class Order{
- // public void method(Object obj) {
- //
- // }
- //}
-