(1)创建源程序MyGroup.java,其中的内容是接口MyGroup的声明。
(2)创建源程序Undergraduate.java,其中的类Undergraduate继承源程序Student.java中的抽象类Student,实现其中的抽象方法print( )。
(3)创建源程序Postgraduate.java,其中的类Postgraduate继承源程序Student.java中的抽象类Student,实现其中的抽象方法print( ),并且,在父类的基础上增加两个新的属性:导师和研究方向。
(4)StuGroup.java,MyGroup.java,Undergraduate.java,Postgraduate.java和Student.java在同一个包中。Main.java在无名包中。
上述源程序可以完成如下任务:
使用者根据提示信息,选择从键盘上输入本科生或者研究生的学生信息,可以添加学生信息、删除学生信息、显示学生信息、按照学生成绩排序等。
项目文件结构截图:
Main.java位于无名包下
//main.java
import 包.*;
import java.util.*;
public class Main
{
public static void main(String[] args)
{
Scanner in=new Scanner(System.in);
StuGroup group=new StuGroup(20); //group可以容纳20个学生
int num; //实际输入的学生信息
System.out.println("要创建本科生信息表还是研究生信息表?\nA.本科生\tB.研究生");
Scanner reader = new Scanner(System.in);
char choice = reader.next().charAt(0);//charAt(index)用于返回索引处的字符
switch(choice)
{
case 'A':
case 'a':
System.out.println("请问要输入多少个本科生的信息?");
num = reader.nextInt();
Student stuB[] = new Undergraduate[num];//stuB[]对象数组是子类Undergraduate对象的上转型对象
for(int i=0;i<num;i++)
{
System.out.println("请输入第"+(i+1)+"位学生的学号,姓名,数学、计算机成绩");
stuB[i] = new Undergraduate(reader.nextInt(), reader.next(),reader.nextDouble(), reader.nextDouble());//从键盘输入学生信息,并赋值给学生
group.addStu(stuB[i]);//参数为引用类型
}
System.out.println("输入的本科生信息为:");
group.print();
group.addStu(new Undergraduate(1312,"shgd",99,98.5));
group.addStu(new Undergraduate(1316,"ddsa",89,88.5));
System.out.println("添加后所有本科生的信息为:");
group.print();
break;
case 'B':
case 'b':
System.out.println("请问要输入多少个研究生的信息?");
num = reader.nextInt();
Student[] stuY = new Postgraduate[num];//stuY[]对象数组是子类Postgraduate对象的上转型对象
for(int i=0;i<num;i++)
{
System.out.println("请输入第"+(i+1)+"位学生的学号,姓名,数学、计算机成绩,导师和研究方向,以空格隔开");
stuY[i] = new Postgraduate(reader.nextInt(), reader.next(),reader.nextDouble(), reader.nextDouble(),reader.next(),reader.next());
group.addStu(stuY[i]);
}
System.out.println("输入的研究生信息为:");
group.print();
group.addStu(new Postgraduate(1312,"shgd",99,98.5,"xyy","os"));
group.addStu(new Postgraduate(1316,"ddsa",89,88.5,"wcl","rgzn"));
System.out.println("添加后所有研究生信息为:");
group.print();
break;
default:
System.out.println("输入错误!!!");
break;
}
System.out.println("删除第几个同学?");
group.removeStu(reader.nextInt());
System.out.println("最新的学生信息为:");
group.print();
group.sort(1);
group.print();//按照数学成绩排序后输出
group.sort(2);
group.print();//按照计算机成绩排序后输出
in.close();
}
}
- Student.java是学生信息类,是抽象类。里面用于学生信息的初始化,get和set方法间接操作域变量,用于对学生信息的设置和获取。并声明了抽象方法print();
- Postgraduate类是Student类的子类,实现研究生信息的初始化,实现抽象方法,输出研究生信息。
- Undergraduate类是Student类的子类,实现本科生信息的初始化,实现抽象方法,输出本科生信息。
- Mygroup.java是接口声明
- StuGroup.java 其中的类实现了接口MyGroup。
是添加学生信息、删除学生信息、显示学生信息、按照学生成绩排序,输出学生信息方法的实现。
上述五个.java文件位于同一“包”文件下。
//Mygroup.java
package 包;
//接口MyGroup的声明。
interface Mygroup
{
boolean addStu(Student x);
Student removeStu(int index);
void sort(int x);
}
//Student.java
package 包;
public abstract class Student
{
//抽象学生类的属性有学号(int),姓名(String),数学成绩(double),计算机成绩(double)
int num;
String name;
double mathScore;
double computerScore;
//【构造方法】
Student(int num,String name,double mathScore,double computerScore)
{
this.num = num;
this.name = name;
this.mathScore = mathScore;
this.computerScore = computerScore;
}
public void getNum(int num)
{
this.num = num;
}
public int setNum()
{
return this.num;
}
public void getName(String name)
{
this.name = name;
}
public String setName()
{
return this.name;
}
public void getMathScore(double mathScore)
{
this.mathScore = mathScore;
}
public double setMathScore()
{
return this.mathScore;
}
public void getComputerScore(double computerScore)
{
this.computerScore =computerScore;
}
public double setComputerScore()
{
return this.computerScore;
}
abstract void print(); //抽象方法,子类要实现这个方法,也就是输出学生的信息
}
//Postgraduate.java
package 包;
//创建源程序Postgraduate.java,其中的类Postgraduate继承源程序Student.java中的抽象类Student,实现其中的抽象方法print( ),并且,在父类的基础上增加两个新的属性:导师和研究方向。
public class Postgraduate extends Student{
String teacher;
String direction;
public Postgraduate(int num, String name, double mathScore, double computerScore,String teacher,String direction)
{
super(num, name, mathScore, computerScore);//子类使用super调用父类的构造方法
this.teacher = teacher;
this.direction = direction;
}
void getTeacher(String teacher)
{
this.teacher =teacher;
}
String setTeacher()
{
return this.teacher;
}
void getDirection(String direction)
{
this.direction =direction;
}
String setDirection()
{
return this.direction;
}
void print( )//子类实现抽象类的方法
{
System.out.println("研究生学生信息为:"+"学号:"+setNum()+",姓名:"+setName()+",数学成绩:"+setMathScore()+",计算机成绩:"+setComputerScore()+"导师:"+setTeacher()+",研究方向:"+setDirection());
}
}
//Undergraduate.java
package 包;
//创建源程序Undergraduate.java,其中的类Undergraduate继承源程序Student.java中的抽象类Student,实现其中的抽象方法print( )。
public class Undergraduate extends Student{
public Undergraduate(int num, String name, double mathScore, double computerScore) {
super(num, name, mathScore, computerScore);//子类使用super调用父类的构造方法
}
void print()
{
System.out.println("本科生信息:"+"学号:"+setNum()+" ,姓名:"+setName()+" ,数学成绩:"+setMathScore()+" ,计算机成绩:"+setComputerScore());
}
}
//StuGroup.java
package 包;
public class StuGroup implements Mygroup
{
private Student[] stu;
private int length; //实际容量
public StuGroup(int len)
{
stu = new Student[len];
}
private boolean isOverflow() //辅助方法,判断数组是否溢出
{
if(this.length<stu.length)
return false;
else
return true;
}
public boolean isEmpty() //判断数组是否为空
{
return this.length==0;
}
public boolean addStu(Student x) //添加学生信息
{
if(isOverflow())
return false;
stu[length++]=x;
return true;
}
public Student removeStu(int index) //删除指定位置的学生信息
{
if(isEmpty())
{
System.out.println("学生表空的~~~删除失败~~~~");
return null;
}
Student temp=stu[index-1];
for(int i=index-1;i<this.length-1;i++)
{
stu[i]=stu[i+1];
}
this.length--;
return temp;
}
public void sort(int x) //按照成绩排序,参数1按数学排序,参数2按计算机排序
{
if(x==1)
{
for(int i =0;i<length-1;i++)
for(int j =0;j<length-i-1;j++)//冒泡排序
{
if(stu[j].setMathScore()<stu[j+1].setMathScore())
{
Student temp;//声明一个对象(引用),用于交换
temp =stu[j+1];
stu[j+1] = stu[j];
stu[j] = temp;
}
}
System.out.println("按数学成绩降序排列为:");
}
else if(x==2)
{
for(int i =0;i<length-1;i++)
for(int j =0;j<length-i-1;j++)
{
if(stu[j].setComputerScore()<stu[j+1].setComputerScore())
{
Student temp;
temp =stu[j+1];
stu[j+1] = stu[j];
stu[j] = temp;
}
}
System.out.println("按计算机成绩降序排名:");
}
}
public void print()
{
for(int i =0;i<length;i++)
stu[i].print();//调用Student子类的print()方法
}
}
结论分析:
(1) 通过抽象类Student和接口MyGroup分析对比总结:
Java提供和支持创建抽象类和接口。它们的实现有共同点,不同点在于:
1.接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。
2.类可以实现很多个接口,类在实现接口方法时一定要用public来修饰,但是只能继承一个抽象类.
3.类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。
4.抽象类可以在不提供接口方法实现的情况下实现接口。
5.Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。
6.Java接口中的成员函数默认是public的。抽象类的成员函数可以是private,protected或者是public。
7.接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的。
(2)Student stuB[] = new Undergraduate[num];//stuB[]对象数组是子类Undergraduate对象的上转型对象,通过本例总结:
上转型对象具有如下特点:
1.上转型对象不能操作子类新增的成员变量(失掉了这部分属性),不能调用子类新增的方法(失掉了一些行为)。
2.上转型对象可以访问子类继承和隐藏的成员变量,也可以调用子类继承的方法或子类重写的方法。上转型对象操作子类继承的方法或子类重写的实例方法,其作用等价于子类对象去调用这些方法。因此,如果子类重写了父类的某个实例方法后,当对象的上转型调用这个实例方法时一定是调用了子类重写的实例方法。