练习一
定义一个Person类,{name,age,job},初始化Person对象数组,有3个person对象,并按照age的值,从小到大进行排序,使用冒泡排序。
注意点:对象的交换方式
public class Person {
private String name;
private int age;
private String job;
public Person(String name, int age, String job) {
this.name = name;
this.age = age;
this.job = job;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", job='" + job + '\'' +
'}';
}
}
class Test01{
public static void main(String[] args) {
Person [] person = new Person[3];
person [0] = new Person("张三",23,"律师");
person [1] = new Person("李娜",25,"美工");
person [2] = new Person("吴彦祖",24,"程序员");
for (int i = 0; i < person.length; i++) {
for (int j = 0; j < person.length-1-i; j++) {
if (person[j].getAge() > person[j+1].getAge()){
Person indxe = null ;//注意对象的交换方式
indxe = person[j];
person[j] = person[j+1];
person[j+1] = indxe;
}
}
}
System.out.println("排序后的效果");
for (int i = 0; i < person.length; i++) {
System.out.println(person[i]);
}
}
}
练习二
写出四种访问修饰符和各自的访问权限
访问修饰符 | 本类 | 同包 | 不同包子类 | 不同包 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
默认 | √ | √ | × | × |
private | √ | × | × | × |
练习三
编写老师类
- 要求有属性:name,age,职称post,salary,薪水级别grade
- 编写业务方法:introduce(),实现输出一个教师的信息
- 编写老师类的三个子类:教授类Professor,副教授类,讲师类。薪水级别为教授1.3/副教授1.2/讲师1.1,且在三个子类中都重写父类的introduce()方法。
- 定义并初始化一个子类对象,调用业务方法,实现对象的基本信息后台打印
public class Teacher {
public String name;
private int age;
private double salary;
private double grade;
public Teacher(String name, int age, double salary, double grade) {
this.name = name;
this.age = age;
this.salary = salary;
this.grade = grade;
}
public void setAge(int age) {
this.age = age;
}
public void setSalary(double salary) {
this.salary = salary;
}
public void setGrade(double grade) {
this.grade = grade;
}
public int getAge() {
return age;
}
public double getSalary() {
return salary;
}
public double getGrade() {
return grade;
}
public String introduce() {
return "Teacher{" +
"name='" + this.name + '\'' +
", age=" + getAge() +
", salary=" + getSalary() +
", grade=" + getGrade() +
'}';
}
}
class Professor extends Teacher{
public Professor(String name, int age, double salary, double grade) {
super(name, age, salary, grade);
}
@Override
public String introduce() {
return super.introduce();
}
}
class Test002{
public static void main(String[] args) {
Professor professor = new Professor("李三",32,30000,1.3);
System.out.println(professor.introduce());
}
}
练习四
通过继承实现员工工资核算打印功能
父类:员工类
子类:部门经理,普通员工
- 部门经理工资=1000+单日工资x天数x等级(1.2)
- 普通员工工资=单日工资x天数x等级(1.0)
- 员工属性:name,单日工资,工作天数
- 员工方法:(打印工资)
- 子类需要重写打印工资的方法
- 实例化两个子类,调用各自的打印工资方法,输入单日工资
//员工类
public class Staff {
public String name;
private double base;//底薪
private double daysal;//日薪
private double grade;//级别
private int days;//天数
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getBase() {
return base;
}
public void setBase(double base) {
this.base = base;
}
public double getDaysal() {
return daysal;
}
public void setDaysal(double daysal) {
this.daysal = daysal;
}
public double getGrade() {
return grade;
}
public void setGrade(double grade) {
this.grade = grade;
}
public int getDays() {
return days;
}
public void setDays(int days) {
this.days = days;
}
public Staff(String name, double daysal, double grade, int days) {
this.name = name;
this.daysal = daysal;
this.grade = grade;
this.days = days;
}
public String printSal(){
double sum = this.base+this.daysal*this.days*this.grade;
return name+"的薪水为="+sum;
}
}
//部门经理类
class Manager extends Staff{
public Manager(String name, double daysal, double grade, int days) {
super(name, daysal, grade, days);
}
@Override
public String printSal() {
return super.printSal();
}
}
//普通员工类
class basicStaff extends Staff{
public basicStaff(String name, double daysal, double grade, int days) {
super(name, daysal, grade, days);
}
@Override
public String printSal() {
return super.printSal();
}
}
class Test004{
public static void main(String[] args) {
Manager wang = new Manager("王经理", 500, 1.2, 30);
basicStaff li = new basicStaff("李三", 400, 1.0, 30);
wang.setBase(1000);
System.out.println(wang.printSal());
li.setBase(0);
System.out.println(li.printSal());
}
}
输出结果:
王经理的薪水为=19000.0
李三的薪水为=12000.0
练习五
设计父类:员工类
子类:工人类(Worker),农名类(Peasant),教师类(Teacher),科学家类(Scientist),服务生类(Waiter)
- 工人,农民,服务生只有基本工资
- 教师不仅有基本工资还有课酬(元/天)
- 科学家除基本工资外,还有年终奖
- 编写一个测试类将各种类型的员工全年工资打印出来
//员工类
public class Staff {
public String name;
private double salary;
public Staff(String name, double salary) {
this.name = name;
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public double printSal(){
return getSalary()*12;
}
}
//工人类
class Worker extends Staff{
public Worker(String name, double salary) {
super(name, salary);
}
}
//老师类
class Teacher extends Staff{
private double remu;
public double getRemu() {
return remu;
}
public void setRemu(double remu) {
this.remu = remu;
}
public Teacher(String name, double salary, double remu) {
super(name, salary);
this.remu = remu;
}
@Override
public double printSal() {
return super.printSal()+getRemu()*365;
}
}
//科学家类
class Scientist extends Staff{
private double bonus;
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
public Scientist(String name, double salary, double bonus) {
super(name, salary);
this.bonus = bonus;
}
@Override
public double printSal() {
return super.printSal()+getBonus();
}
}
//测试类
class Test005{
public static void main(String[] args) {
Worker worker = new Worker("李三", 3000);
System.out.println("农民"+worker.name+"的年收入为="+worker.printSal());
Teacher teacher = new Teacher("张明",5000,100);
System.out.println("教师"+teacher.name+"的年收入为="+teacher.printSal());
Scientist scientist = new Scientist("李想",6000,20000);
System.out.println("科学家"+scientist.name+"的年收入为="+scientist.printSal());
}
}
练习六
Grand Father和Son在同一个包,在下方的语句中this和super都可以调用哪些属性和方法
//Grand
class Grand{
String name = "AA";
private int age = 100;
public void g1(){}
}
//Father
class Father extends Grand{
String id = "001";
private double score;
public void f1(){
//super可以访问哪些成员?
//this可以访问哪些成员
}
}
//Son
class Son extends Father{
String name = "BB";
@Override
public void g1(){}
public void show(){
//super可以访问哪些成员?
//this可以访问哪些成员}
}
Father 类:
的f1方法中super可以访问:name=“AA”,和g1方法。age变量由于是private修饰且没有get方法,无法访问
this可以访问 name=“AA”,score,id=“001”,g1方法,f1()方法
Son类:
的g1方法中super可以访问:name=“AA”(父类的),id =”001“,g1方法(超类的),f1方法(父类的)
this可以访问:name = “BB”(自己的),id =”001“,g1方法(自己的),f1方法(父类的),show方法
练习七
写出程序结果
class Test{
String name = "Rose";
Test(){
System.out.println("Test");
}
Test(String name){
this.name = name;
}
}
class Demo extends Test{
String name = "jack";
Demo(){
super();
System.out.println("Demo");
}
Demo(String s){
super(s);
}
public void test(){
System.out.println(super.name);
System.out.println(this.name);
}
public static void main(String[]args){
new Demo().test();
new Demo("john").test();
}
}
输出结果是:
Test
Demo
Rose
jack
john
jack
练习八
拓展下面的BankAccount类(银行账户)
public class BankAccount{
private double balance;
public BankAccount(double initialBalance){
this.balance = initialBalance;
}
public void deposit(double amount){//存款方法
balance += amount;
}
public void withdraw(double amount){//取款方法
balance -= amount;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
要求:
- 在上面类的基础上拓展 新类 CheckingAccount类,对每次存款取款都收取1元的手续费
- 在前一个拓展的基础上增加一个新类,SavingAccount使每个月都有利息产生(earnMonthlyInterest方法被调用),并且每月有三次抵扣存取款的手续费。再earnMonthlyInterest方法中重置交易次数
public class BankAccount{
private double balance;
public BankAccount(double initialBalance){
this.balance = initialBalance;
}
public void deposit(double amount){//存款方法
balance += amount;
}
public void withdraw(double amount){//取款方法
balance -= amount;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
//CheckingAccount 类
class CheckingAccount extends BankAccount{
public CheckingAccount(double initialBalance) {
super(initialBalance);
}
@Override
public void deposit(double amount) {
super.deposit(amount-1);
}
@Override
public void withdraw(double amount) {
super.withdraw(amount+1);
}
}
//SavingAccount 类
class SavingAccount extends BankAccount{
public SavingAccount(double initialBalance) {
super(initialBalance);
}
int count = 3;
double res = 0.1;
@Override
public void deposit(double amount) {
if (count >= 1) {
super.deposit(amount);
//免手续费存钱
count--;
}else{
super.deposit(amount-1);
//扣一块钱到行长的卡里
}
}
@Override
public void withdraw(double amount) {
if (count >= 1) {
super.withdraw(amount);
//免手续费取钱
count--;
}else{
super.withdraw(amount+1);
//扣一块钱到行长的卡里
}
}
public void earnMonthlyInterest(){
super.deposit(this.getBalance()*res);//把利息存进账户
count = 3;//重置免手续的次数
}
}
class Test006{
public static void main(String[] args) {
SavingAccount s = new SavingAccount(100);
s.deposit(500);
s.deposit(500);
s.deposit(500);
System.out.println(s.getBalance());
s.deposit(500);
System.out.println(s.getBalance());
s.earnMonthlyInterest();
s.withdraw(200);
System.out.println(s.getBalance());
}
}
练习九
设计一个Point类,其x和y坐标可以通过构造器提供。定义一个子类LabeledPoint,其构造器接收一个标签值和x,y坐标。比如new LabeledPoint(“black”,1929,230.07) 写出对应构造器即可。
public class Point {
public double x;
public double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}
class LabeledPoint extends Point{
public String label;
public LabeledPoint(String label,double x, double y) {
super(x, y);
this.label = label;
}
}
练习十
编写Doctor类(name,age,sal)有相应的get和set方法,3个参数的构造器
要求重写父类的equals()方法public boolean equals(Object obj)
并判断测试类中创建的两个对象是否相等。相同条件为:属性全相同就算相等
public class Doctor {
public String name;
private int age;
private double salary;
public Doctor(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public boolean equals(Object obj) {
if (this == obj){
return true;}
Doctor doc = (Doctor) obj;//向下转型
return this.name.equals(doc.name) && this.age == doc.getAge() && this.salary == doc.getSalary() ;
}
}
class Test007{
public static void main(String[] args) {
Doctor d1 = new Doctor("李四", 22, 3000);
Doctor d2 = new Doctor("李四", 23, 3000);
System.out.println(d1.equals(d2));
}
}
练习十一
Person类中有run方法和eat方法,他的子类Student类重写了run方法且还有一个自己的study方法。
写出向下转型和向上转型的代码,并说出各自都可以调用什么方法。会输出什么
案例
public class Person {
public void run(){
System.out.println("Person run");
}
public void eat(){
System.out.println("Person eat");
}
}
class Student extends Person{
@Override
public void run() {
System.out.println("Student run");
}
public void study(){
System.out.println("Student study");
}
}
答案
class Test09{
public static void main(String[] args) {
Person person = new Student();//向上转型
//可以调用Student类的run方法,输出Student run
person.run();//编译阶段是父类Person的run方法,运行阶段是子类Student的run方法
//可以调用Person类的eat方法,输出Person eat
person.eat();//编译和运行都是父类的eat方法,因为子类中没有eat方法
Student student = (Student) person;//向下转型
//可以调用Student类的study方法,输出Student study
student.study();
//可以调用Student类的run方法,输出Student run
student.run();//编译和运行都是子类
//可以调用Person类的eat方法,输出Person eat
student.eat();
}
}
练习十二
说出 == 和equals的区别
名称 | 概念 | 用于判断基本数据 | 用于判断引用类型 |
---|---|---|---|
== | 比较运算符 | 判断值是否相等 | 判断两个对象的地址是否相同 |
equals | Object类的方法 | 无法判断 | 默认判断两个对象的地址是否相同 |
注意点:
- equals方法是Object类的方法,所以java中所有类都会继承equals方法
- equals虽然默认是判断对象的地址是否相同,但是子类中往往会重写为判断两个对象的属性是否相同
练习十三
案例描述:
- 定义一个Student类,Student类有 名称name,性别sex,年龄age,学号stu_id,将4个属性封装到构造器赋值
- 定义一个Teacher类,属性有name ,sex,age,工龄work_age,同样封装到构造器
- 学生有一个学习的方法(study),输出“我承诺,我会好好学习”
- 老师有一个教学的方法(teach),输出”我承诺,我会好好教学“
- 学生和老师都有玩的方法(play),学生玩的是足球,老师玩的是象棋。分别返回字符串 xx爱玩足球和xx爱玩象棋,xx代表名字。
- 抽象出一个父类Person类,将共同的属性和方法封装到Person类
- 定义多态数组,里面保存2个学生和2个老师,要求按年龄从高到低排序
- 定义方法,形参为Person类,功能调用学生的study或教师的teach方法。
//Person类
public class Person {
private String name;
private char sex;
private int age;
public String play(){
return null;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
'}';
}
public String printPlay(){
return this.play();
}
public void printInfo(){}
}
//Student类
public class Student extends Person{
private int stu_id;
public Student(String name, char sex, int age, int stu_id) {
setName(name);
setAge(age);
setStu_id(stu_id);
setSex(sex);
}
public void study(){
System.out.println("我承诺,我会好好学习");
}
@Override
public String play() {
return getName()+"爱玩足球";
}
public int getStu_id() {
return stu_id;
}
public void setStu_id(int stu_id) {
this.stu_id = stu_id;
}
@Override
public void printInfo() {
System.out.println("学生的信息:\n" +
"姓名:"+getName()+"\n年龄:"+getAge()+"\n性别:"+getSex()+"\n学号:"+getStu_id());
study();
}
}
//Teacher类
public class Teacher extends Person{
private int work_Age;
public Teacher(String name, char sex, int age, int work_Age) {
setName(name);
setAge(age);
setWork_Age(work_Age);
setSex(sex);
}
public void teach(){
System.out.println("我承诺,我会好好教学");
}
@Override
public String play() {
return getName()+"爱下象棋";
}
public int getWork_Age() {
return work_Age;
}
public void setWork_Age(int work_Age) {
this.work_Age = work_Age;
}
@Override
public void printInfo() {
System.out.println("老师的信息:\n" +
"姓名:"+getName()+"\n年龄:"+getAge()+"\n性别:"+getSex()+"\n工龄:"+getWork_Age());
teach();
}
}
//测试类
public class Test006 {
public static void main(String[] args) {
Person[] person = new Person[4];
person [0] = new Student("李涛",'男',18,0012);
person [1] = new Student("宋琪",'女',19,0022);
person [2] = new Teacher("张杰",'男',30,3);
person [3] = new Teacher("李娜",'女',28,5);
//使用冒泡循环进行排序
for (int i = 0; i < person.length-1; i++) {
for (int j = 0; j < person.length-1-i; j++) {
if (person[j].getAge() > person[j+1].getAge()){
Person indx = null;
indx = person[j];
person[j] = person[j+1];
person[j+1] = indx;
}
}
}
//查看排序后的情况
for (int i = 0; i < person.length; i++) {
person[i].printInfo();
System.out.println(person[i].printPlay());
System.out.println("---------------");
}
}
}
输出结果:
学生的信息:
姓名:李涛
年龄:18
性别:男
学号:10
我承诺,我会好好学习
李涛爱玩足球
===========
学生的信息:
姓名:宋琪
年龄:19
性别:女
学号:18
我承诺,我会好好学习
宋琪爱玩足球
===========
老师的信息:
姓名:李娜
年龄:28
性别:女
工龄:5
我承诺,我会好好教学
李娜爱下象棋
===========
老师的信息:
姓名:张杰
年龄:30
性别:男
工龄:3
我承诺,我会好好教学
张杰爱下象棋
===========
练习十四
在main方法中执行:C c = new C(); 会输出什么?
class A{
public A(){
System.put.println("我是A类的无参构造器");
}
]
class B extends A{
public B(){
System.put.println("我是B类的无参构造器");
}
public B(String name){
System.put.println(name+"我是B类的有参构造器");
}
}
class C extends B{
public C(){
this("hello");
System.put.println("我是C类的无参构造器");
}
public C(String name){
super("hahaha");
System.put.println(name+"我是C类的有参构造器");
}
}
在main方法中执行 C c = new C();
- 首先由于没有传入参数,默认调用无参构造器 ,
- 由于无参构造器的第一行语句是this(“hello”);,所以会调用C类的有参构造器,且传入参数hello
- C类的有参构造第一条语句是super(”hahaha“)所以会调用B类的有参构造器
- B类的有参构造器由于默认会有一个super();调用B类的父类构造器,所以会进入A类的无参构造器输出:我是A类的无参构造器
- 然后再回到B类有参构造器将传入的”hahaha“拼接语句输出 hahaha我是B类的有参构造器
- 接着返回C类的有参构造器,输出下面的语句 用C类的无参构造器传入的”hello“凭借输出: hello我是C类的有参构造器
- 再返回到C类的无参构造继续输出下面的:我是C类的无参构造器
所以会输出:
我是A类的无参构造器
hahaha我是B类的有参构造器
hello我是C类的有参构造器
我是C类的无参构造器
练习十五
- 什么是多态,多态的具体体现有哪些?
-. 多态:方法或对象具有多种形态,是OOP编程的第三特征,建立再封装和继承之上
-. 方法的多态:重载,重写
-.对象的多态:对象的编译类型和运行类型可以不一致,编译类型在定义时就确定了,无法变化
而运行类型是可以变化的,可以通过getClass()查看实时的运行类型
列如:
Class A{}
Class B extends A{}
Class C extends B{}
A obj = new B();
此时obj的编译类型是A ,运行类型是B
A b1 = obj
此时obj将 它那的对象地址复制一份给了 b1
obj = new C()
此时 obj的运行类型变化成了 C
obj = b1
此时b1将 它那的对象地址复制一份给了 obj,所以obj的运行类型又变回了B
- java的动态绑定机制是什么?
- 当调用对象的方法时,该方法会和对象的内存地址(运行类型),绑定在一起,如果没有找到,则就父类找
- 当调用对象的属性时,没有动态绑定机制,谁调用,就使用谁那里的。也就是看编译类型