11.抽象类和接口
1.在JDK1.7中,下述说法中抽象类与接口的区别与联系正确的有哪些? [多选题]全选
您的回答:
A、抽象类中可以有普通成员变量,接口中没有普通成员变量。
B、抽象类和接口中都可以包含静态成员常量。
C、一个类可以实现多个接口,但只能继承一个抽象类
D、抽象类中可以包含非抽象的普通方法,接口中的方法必须是抽象的,不能有非抽象的普通方法。
2.抽象类与接口的区别是什么?
抽象类中可以有一个或多个抽象方法,而接口中的方法必须都是抽象方法 接口所属性只能是publist static final修饰的,而抽象类中的属性则可以是任何类型的属性; 抽象类只能单继承,接口之间可以是多继承,一个类可以实现多个接口 通常来说,抽象类可以表示同一类事物,而接口可以表示一种能力
3.类和类之间的关系有哪几种?分别是什么?每种关系在代码中是如何体现的?
共5种
继承
关联
聚合
组合
依赖
继承:is
判断:is
代码:extends
依赖:偶然发生的联系,
判断:use 代码:方法中的参数,或方法中的局部变量;
关联:是一种强依赖;
判断:has 代码:作为属性来存在; 聚合:关联的一种特殊形式,代码相同;都是属性;主要强调的是整体和局部 组合:关联的一种特殊形式,代码相同,都是属性;整体和局部有相同的生命周期;
4.【编程题】类之间的关系 要求:先说明由几个类;然后确定类和类(接口)的关系,画出类图;再编程来实现
1.模拟司机(Driver)可以开汽车(Car);而汽车不属于司机;
2.武将,可以使用各种武器(刀,弓,矛)进行攻击,武将最多只能有一把武器,可以对敌军的人物造成伤害;
3.电脑可以从U盘,数据相机,mp3等电子设备中下载数据;
4.班级由多个学生和只有一个教师组成;
更改老师,添加,删除学生;
5.模拟天天酷跑中的主人公,主角(Actor)可以有一个宠物,宠物可以有猫,狗,免,主角在跑的时侯,他的宠物可以跟着一起跑;
6.模拟一下开心牧场;农场中有农户,各种动物(牛,马,羊,鸡等),农户可以喂养动物;
略(翻笔记)类图!!!
笔记
抽象类(abstract)
抽象方法,没有方法的实现体。如果一个类中含有抽象方法,这个类一定是抽象类。抽象类中也可以包含非抽象方
法
抽象类不能实例化,可以定义一个类继承抽象类 ,重写所有的抽象方法,创建这个子类的对象
代码
public abstract class Test {
//属性
private String name;
//常量属性
public static final String IP = "192.168.1.11";
//构造器
public Test(){
}
//定义非抽象方法
public void method2(){
}
//定义了一个抽象方法
public abstract void method();
}
public class TestSub extends Test {
@Override
public void method() {
System.out.println("TestSub method");
}
public static void main(String[] args)
{
TestSub ts = new TestSub();
ts.method(); } }
模板设计模式
定义一个抽象类,在抽象类中的非抽象方法中 写好一个算法过程,在这个方法中调用抽象类中的抽象方法,就相
当于定义了一个模板类。要使用这个模板类,必须要定义一个子类继承模板类,重写抽象方法,就可以调用子类继
承的非抽象方法了。
public abstract class Bank {
public abstract double getBenjin();
public abstract double getLv();
public double lixi(){
return getBenjin()*getLv();
}
}
public class BankSub extends Bank {
@Override
public double getBenjin() {
return 10000; }
@Override
public double getLv() {
return 0.03; }
public static void main(String[] args) {
BankSub b = new BankSub();
System.out.println(b.lixi());
} }
接口(interface)
定义接口
语法:
[<修饰访问符>] interface 接口名{
[常量]
[抽象方法]
}
接口一定是public的
接口的属性,默认是有public static final修饰,因为接口中只能定义常量
接口中的方法,默认是有abstract修饰,因为接口中的方法都是抽象方法
public interface ITest {
//public static final String name = "test";
String name = "test";
public void method(); }
实现接口
定义一个类实现接口(implements),重写接口中所有的方法
public class TestImpl implements ITest{
@Override
public void method() {
System.out.println("TestImpl method方法");
}
public static void main(String[] args) {
TestImpl t = new TestImpl();
t.method();
} }
一个类可以实现多个接口
public class TestImpl implements ITest,IUSB{
@Override
public void method() {
System.out.println("TestImpl method方法");
}
@Override
public void tran() {
System.out.println("USB 传输数据");
}
public static void main(String[] args) {
TestImpl t = new TestImpl();
t.method();
} }
一个类可以继承一个类并实现多个接口,把extends写在implements的前面
public class TestImpl extends Computer implements ITest,IUSB{
@Override
public void method() {
System.out.println("TestImpl method方法");
}
@Override
public void tran() {
System.out.println("USB 传输数据"); }
public static void main(String[] args) {
TestImpl t = new TestImpl();
t.method(); } }
接口和接口之间也可以继承,可以是多继承
public interface ITest extends ITest1,ITest2{
//public static final String name = "test";
String name = "test";
public void method();
}
接口的作用
- 制定标准规范
public interface IResource {
public byte[] getResource(String id);
}
public class AQY implements IResource{
@Override
public byte[] getResource(String id) {
System.out.println("爱奇艺:通过视频的id获得视频对象");
return null;
}
}
public class Ten implements IResource{
@Override
public byte[] getResource(String id) {
System.out.println("腾讯视频:根据名字获得视频");
return new byte[0];
}
}
- 做设计
软件设计时降低耦合度
在一个类中 调用了 另一个类的功能,也就是在一个类中使用了另一个类的名字,两个类具有耦合度
public class GuTianLe implements Player{
public void play(){
System.out.println("古天乐:姑姑...");
}
}
public class LiRuoTong implements Player{
public void play(){
System.out.println("李若彤:过儿...");
}
}
public class PlayerFactory {
public static Player getManPlayer(){
return new ZhaoSi();
}
public static Player getWomanPlayer(){
return new LiRuoTong();
}
}
public class Movie {
public static void main(String[] args) {
//拍摄 神雕侠侣 电视剧
//执行5000次 GuTianLe类 、LiRuoTong类 和 Movie类的耦合度非常高
//面向接口编程
Player p1 = PlayerFactory.getManPlayer();
p1.play();
Player p2 = PlayerFactory.getWomanPlayer();
p2.play();
}
}
12。内部类及综合
1.有以下·程序片段且Interesting不是内部类,下列哪个选项不能插入到行1。( )
1.
2.public class Interesting{
3. // 省略代码
4.}
[单选题]
您的回答:
C 、class OtherClass{ } ×
正确答案:
D、public class MyClass{ }√
2.java中的内部类有几种?分别是什么?
您的回答:
成员内部类
静态内部类
局部内部类
匿名内部类
3、 【编程题】编写工资系统,实现不同类型员工(多态)的按月发放工资。如果当月出现某个Employee对象的生日,则将该雇员的工资增加100元。 实验说明:
(1)定义一个Employee类,该类包含:
private成员变量name,number,birthday,其中birthday 为MyDate类的对象;
abstract方法earnings();toString()方法输出对象的name,number和birthday。
(2)MyDate类包含:
private成员变量month,day,year;
toDateString()方法返回日期对应的字符串:xxxx年xx月xx日
(3)定义SalariedEmployee类继承Employee类,实现按月计算工资的员工处理。该类包括:
private成员变量monthlySalary;
实现父类的抽象方法earnings(),该方法返回monthlySalary值;toString()方法输出员工类型信息及员工的name,number,birthday。
(4)参照SalariedEmployee类定义HourlyEmployee类,实现按小时计算工资的员工处理。该类包括:
private成员变量wage和hour;
实现父类的抽象方法earnings(),该方法返回wage*hour值;toString()方法输出员工类型信息及员工的name,number,birthday。
(4)定义PayrollSystem类,创建Employee变量数组并初始化,该数组存放各类雇员对象的引用。利用循环结构遍历数组元素,输出各个对象的类型,name,number,birthday,以及该对象生日。当键盘输入本月月份值时,如果本月是某个Employee对象的生日,还要输出增加工资信息。
提示:
//定义People类型的数组
People c1[]=new People[10];
//数组元素赋值
c1[0]=new People("John","0001",20);
c1[1]=new People("Bob","0002",19);
//若People有两个子类Student和Officer,则数组元素赋值时,可以使父类类型的数组元素指向子类。
c1[0]=new Student("John","0001",20,85.0);
c1[1]=new Officer("Bob","0002",19,90.5);
public class MyDate {
private int year;
private int month;
private int day;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public MyDate(int year, int month, int day) {
super();
this.year = year;
this.month = month;
this.day = day;
}
public String toDateString() {
return year+"年"+month+"月"+day+"日";
}
}
public abstract class Employee {
private String name;
private int number;
private MyDate birthday;
public abstract double earnings();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public MyDate getBirthday() {
return birthday;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
public Employee(String name, int number, MyDate birthday) {
super();
this.name = name;
this.number = number;
this.birthday = birthday;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "姓名:"+name+",工号:"+number+",生日:"+birthday.toDateString();
}
}
public class SalariedEmployee extends Employee{
private double monthlySalary;
@Override
public double earnings() {
// TODO Auto-generated method stub
return monthlySalary;
}
public SalariedEmployee(String name, int number, MyDate birthday, double monthlySalary) {
super(name, number, birthday);
this.monthlySalary = monthlySalary;
}
@Override
public String toString() {
return super.toString()+",工资"+monthlySalary;
}
}
public class HourlyEmployee extends Employee{
private double wage;
private double hour;
public HourlyEmployee(String name, int number, MyDate birthday, double wage, double hour) {
super(name, number, birthday);
this.wage = wage;
this.hour = hour;
}
@Override
public double earnings() {
return wage*hour;
}
}
public class PayrollSystem {
public static void main(String[] args) {
Employee[] employees = new Employee[] {
new HourlyEmployee("甲", 1000, new MyDate(1995, 11, 12), 100, 2),
new SalariedEmployee("乙", 10020, new MyDate(1990, 12, 12), 10000),
new SalariedEmployee("丙", 10021, new MyDate(1993, 11, 10), 15000)
};
Scanner scanner = new Scanner(System.in);
System.out.println("请输入当前的月份:");
int month = scanner.nextInt();
for(int i = 0;i
4.编程题】自已封装一个动态数组类,可以根据用户传递的数据,动态的对数组的长度进行扩展;
类名是:MyArray 需要实现方法有:
void add(int value); //追加一个值
vold remove(int index); //根据索引,删除一个值
void add(int position,int value); //在指定位置插入一个数值
void set(int position,int value); //修改某个位置的数值
int get(int index); //根据索引,获得元数的值
int size(); //获得动态数组中元素的个数;。
import java.util.Arrays;
class MyArray{
private int size = 0;//数组的长度
private int [] array = new int[10];
//追加一个值
public void add(int n) {
expand();
array[size++] = n;
}
//扩容
public void expand() {
if(size == array.length) {
int [] newarray = new int[array.length*3/2+1];
System.arraycopy(array, 0, newarray, 0, array.length);
array = newarray;
}
}
//获得数组的元素个数
public int getSize() {
int sum = size;
System.out.println("当前数组的元素个数是:"+sum);
return sum;
}
//获得当前数组的长度
public int getLength() {
int sum = array.length;
System.out.println("当前数组的长度是:"+sum);
return sum;
}
//根据索引获得值
public int get(int index) {
int v = array[index];
System.out.println("该索引对应的值是:"+v);
return v;
}
//修改某个位置上的元素值
public void set(int position,int value) {
System.out.println(position+"位置上的元素值被修改为:"+value);
array[position] = value;
}
//输出数组
public void output() {
System.out.println(Arrays.toString(array));
}
//删除某个位置上的值
public void remove(int index) {
System.out.println("删除位置"+index+"上的元素值后,数组变为:");
array[index] = array[index+1];
for(int i = index+1;i < array.length-1;i++) {
array[i] = array[i+1];
}
}
//在某个位置上插入元素值
public void add(int position,int value) {
System.out.println("在位置"+position+"上插入的元素"+value+"后,数组变为:");
for(int i = size;i > position;i--) {
array[i+1] = array[i];
}
array[position] = value;
}
}
public class _2 {
public static void main(String[] args) {
MyArray a = new MyArray();
for(int i = 0;i < 13;i++) {
a.add(i+20);
System.out.println(i+20);
}
a.getSize();
a.getLength();
a.get(3);
a.set(3, 100);
System.out.println("修改后得数组是:");
a.output();
a.remove(6);
a.output();
a.add(6, 999);
a.output();
}
}
笔记
内部类
定义在类中的类,叫内部类
public class Outer {
class Inner{
}
}
内部类的作用是为外部类提供服务的一个类。由于内部类是外部类的成员,因此外部类可以直接调用内部类的属性
和方法
创建内部类对象
public class Outer {
public void method(){
//外部类Outer中直接创建内部类Inner的对象
Inner inner = new Inner();
}
class Inner{
private String name; }
}
public class Main {
public static void main(String[] args) {
//创建Inner内部类的对象
Outer outer = new Outer();
//比较少见
Outer.Inner inner = outer.new Inner();
}
}
定义静态内部类
匿名内部类
创建一个没有名字的类的对象
public static void main(String[] args) {
//创建了一个Animal的子类对象 ,子类没有名字
Animal animal = new Animal(){
@Override
public void eat() {
System.out.println("cat eat"); }
};
animal.eat();
//等同于
class NoName extends Animal{
@Override
public void eat() {
System.out.println("cat eat");
}
}
Animal a = new NoName(); }
某个类只创建了一次对象,可以使用匿名内部类的写法
计算器的例子
public class Cal {
JButton btn0 = new JButton("0");
JButton btn1 = new JButton("1");
JButton btn2 = new JButton("2");
JButton btnAdd = new JButton("+");
JButton btnSub = new JButton("-");
public Cal(){
btn0.addActionListener(new NumberBtnListener());
btn1.addActionListener(new NumberBtnListener());
btn2.addActionListener(new NumberBtnListener());
btnAdd.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//读取文本框中数字,进行加运算
}
});
btnSub.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//读取文本框中数字,进行减运算
}
});
}
class NumberBtnListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
//读取按钮的文本,显示到文本框中
}
}
}



