学堂在线—Java程序设计—课程笔记(第4章 接口与多态)

4 接口与多态

4.1 接口

  1. 接口:纯抽象类,只能有抽象方法;
    接口中可以规定方法的原型,不规定方法主体;
    可以包含基本数据类型的数据成员,都默认为static和final;
  2. 接口作用:
    继承多个设计;
    建立类和类之间的“协议”(接口可以按照类的不同功能分组,让没有继承/组合关系的类实现统一对外接口);
    接口可以隐藏实现的细节;
  3. 声明格式:[接口修饰符] interface接口名称 [extends父接口名]
    接口数据成员一定要有初值且不能再更改(可省略final);
    接口中方法可省略public 和 abstract;
  4. 实现接口:implements,必须实现接口中所有方法,来自接口的方法必须public;
    可以同时实现多个接口;
  5. 接口可以多继承,实现接口时必须实现超接口;

4.2 类型转换、方法的查找

  1. 类型转换规则:
    基本类型之间转换:将值从一种类型转换成另一种类型;
    引用变量类型转换:将引用转换为另一类型的引用,并不改变对象本身类型;
    引用变量转型:转换为超类(向上转型)、所属类实现的接口(向上转型)、引用指向的对象的类型(唯一可以向下转型);
    引用被转换为其超类引用后,只能访问超类中声明的方法;
  2. 隐式类型转换(自动类型转换):
    基本数据类型存储容量低自动向存储容量高转换;
    引用变量被转成更一般的类(超类),被塑形为对象所属类实现接口;
  3. 显示类型转换(强制转换):
    基本数据类型(类型名)内容,可能丢失数据;
    引用变量向下转型,只能转为引用指向的对象的类型;
  4. 类型转换主要应用场合:赋值转换,方法调用转换,算数表达式转换,字符串转换;
  5. 实例方法的查找:从对象创建时的类开始,沿类层次向上查找;
    类方法的查找:在引用变量声明时所属类中查找;

4.3 多态的概念、应用举例

  1. 多态:超类对象和从相同超类派生出的多个子类的对象,可被当作同一种类型对象对待;
    实现同一接口不同类型的对象,可被当作同一种类型的对象对待;
    可向这些不同类型的对象发送同样的消息,由于多态性,这些不同类对象响应同一消息时的行为可以有所差别;
  2. 多态的目的:使代码简单且容易理解,程序可扩展性更好;
  3. 绑定:将一个方法调用表达式与方法体代码结合起来;
    早绑定:程序运行前绑定;
    晚绑定(动态绑定/运行期绑定):基于对象类别在程序运行时绑定;
  4. 应用举例:二次分发;

4.4 构造方法和多态性

  1. 构造子类对象时构造方法的调用顺序:
    首先调用超类的构造方法,最后执行当前子类构造方法;
    未写明时会直接调用超类空参数的构造方法;
  2. 实现构造方法的注意事项:
    用尽可能少的动作把对象状态设置好;
    尽量避免调用任何方法(构造方法中调用动态方法可能存在出现潜在问题,尽量避免);
    构造方法内唯一能够安全调用的是超类中final方法(及private方法)。

部分习题

1.以下是接口I的定义:
interface I{
void setValue(int val);
int getValue();
}

以下哪段代码能够通过编译:
A. class A extends I{int value;public void setValue(int val){value=val;}public int getValue(){ return value;}}
B. class B implements I{int value; void setValue(int val){value=val;} public int getValue(){ return value;}}
C. interface C extends I {void add();} interface C extends I {void add();
D. interface D implements I{void add();}

答案:选择C;

选项A:The type I cannot be the superclass of A; a superclass must be a class;
选项B:Cannot reduce the visibility of the inherited method from I;(未加public)
选项D:implements未实现全部方法;

2.已知

import java.io.*;
class Person{
	public static void print(){System.out.print("Person");}
}
class Employee extends Person{
	public void print(){
	System.out.print("Employee");}
}
class Manager extends Employee{
	public void print(){
	System.out.print("Manager");}
}
public class Test{
	public static void main(String[] args){
	Manager man = new Manager();
	Employee emp1 = new Employee();
	Employee emp2 = (Employee)man;
	Person person = (Person)man;
	emp2.print();
	System.out.print("#");
	person.print();}
}

对于以上代码,其输出结果是
A. Employee#Person
B. Manager#Person
C. Employee#Manager
D. Manager#Manage

答案:选择D。

对于题2中的Person,Employee,Manager的print方法,若均是static的方法,其输出结果是
A. Employee#Person
B. Employee#Person
C. Manager#Person
D. Manager#Manager

答案:选择A。

实例方法的查找:从对象创建时的类开始,沿类层次向上查找;
类方法的查找:在引用变量声明时所属类中查找;

3.关于下面的程序,说法正确的是()

class Base{
	int m;
	public Base(int m){ this.m=m+1;}
}
public class TestDemo extends Base{
	public TestDemo(){
	m=m+1;
	}
	public static void main(String args[]){
		TestDemo t = new TestDemo();
		System.out.println(t.m);
	}
}

A. 输出结果为0
B. 输出结果为1
C. 输出结果为2
D. 编译错误

答案:选择D。

超类中构造函数有参数,无默认构造函数,子类构造时不能省略;

4.以下哪个语句可以放到插入行

class A{}
class B extends A{}
class C extends A{}
public class Test{
public static void main(String[] args){
A x= new A();
B y= new B();
C z= new C();
//此处插入一条语句
}}

A. x=y
B. z=x
C. z=(C )y
D. y=(A)y

答案:选择A。

引用变量可被转成更一般的类(超类),被塑形为对象所属类实现接口;
引用变量向下转型,只能转为引用指向的对象的类型。

编程练习题

1. 偶数分解

题目

歌德巴赫猜想:任何一个大于六的偶数可以拆分成两个质数的和,打印出所有的可能
输入n为偶数,输出n的所有分界可能
如输入
100
输出:
100=3+97
100=11+89
100=17+83
100=29+71
100=41+59
100=47+53

思路

无复杂度要求,可先计算n范围内的质数,再遍历求解。

代码

import java.util.Scanner;

public class homework4_1 {
	static boolean prime(int num) {
		for (int i = 2; i < num; i++)
			if ( num % i == 0 )
				return false;
		return true;
	}	
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		boolean[] boo = new boolean[n];
		in.close();
			
		boo[2] = true;
		for (int i = 3; i < n; i++) {
			boo[i] = prime(i);
		}
		
		int hn = n / 2 + 1;
		for (int i = 3; i < hn; i++) {
			if ( boo[i] && boo[n - i] )
				System.out.println(n + "=" + i + "+" + (n - i));
		}		
	}
}

2. 最大公约数和最小公倍数

题目

输入两个正整数m和n,求其最大公约数和最小公倍数
输入
34 8
输出
2 136

思路

先求解出最大公约数,计算得到最小公倍数。

代码

import java.util.Scanner;

public class homework4_2 {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int a = in.nextInt();
		int b = in.nextInt();
		in.close();
		
		if ( a < b ) {
			int tmp = a;
			a = b;
			b = tmp;
		}
		
		int gcd;
		if ( a % b == 0) 
			gcd = b;
		else {
			int hb = b / 2 + 1;
			gcd = 1;
			for (int i = 2; i < hb; i++) {
				if (( a % i == 0 ) && ( b % i == 0))
					gcd = i;
			}
		}
		
		int lcm = a * b / gcd;
		System.out.println(gcd + " " + lcm);
		
	}
}

3. 铺砖问题

题目

有两种砖,分别是1 * 1的砖和1 * 2的砖,用这两种砖铺1 * N的地面,问共有多少种铺法。输入为N,请输出相应的铺法数
输入:
3
输出:
3

思路

动态规划,划分为 [n - 1] 和 [n - 2] 两种状态,ans[i] = ans[i - 2] + ans[i - 1],结果即斐波那切数列。

代码

import java.util.Scanner;

public class homework4_3 {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		in.close();
		
		long[] ans = new long[n + 1];
		ans[1] = 1;
		ans[2] = 2;
		if (n > 2) {
			for (int i = 3; i <= n; i++) {
				ans[i] = ans[i - 2] + ans[i - 1];
			}
		}
		
		System.out.println(ans[n]);
	}
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值