这一章讲的是接口,
其中抽象和C++中的纯虚函数特别相似,我会在Java编程思想专栏做完以后,专门写一篇文章来对比C++和Java的不同。
1.修改第8章练习9中的Rodent,使其成为一个抽象类。只要可能,就将Rodent的方法声明为抽象方法。
package job;
import java.util.*;
abstract class Rodent{
abstract void bit();
}
class Mouse extends Rodent{
@Override
void bit(){
System.out.println("Mouse bit");
}
}
class Gerbil extends Rodent{
@Override
void bit(){
System.out.println("Gerbil bit");
}
}
class Hamster extends Rodent{
@Override
void bit(){
System.out.println("Hamster bit");
}
}
public class Main {
public static void main(String[] args) {
Rodent[] a= {
new Mouse(),
new Gerbil(),
new Hamster(),
};
for(Rodent e:a){
e.bit();
}
}
}
注意:抽象函数没有主体!
2.创建一个不包含任何抽象方法的抽象类,并验证我们不能为该类创建任何实例。
package job;
import java.util.*;
abstract class A{
}
public class Main {
public static void main(String[] args) {
new A();//,Error:(13, 9) java: job.A是抽象的; 无法实例化
}
}
3.创建一个基类,让它包含抽象方法print(),并在导出类中覆盖该方法。覆盖后的方法版本可以打印导出类中定义的某个整型变量的值。在定义该变量之处,赋予它非零值。在基类的构造器中调用这个方法。现在,在main()方法中,创建一个导出类对象,然后调用它的print()方法。请解释发生的情形。
package job;
import java.util.*;
abstract class A{
A(){
print();
}
abstract void print();
}
class B extends A{
int x=6;
void print(){
System.out.println("printing x="+x);
}
}
public class Main {
public static void main(String[] args) {
B b=new B();
}
}
output:printing x=0
与运行顺序有关,详情请看第八章。
4.创建一个不包含任何方法的抽象类,从它那里导出一个类,并添加一个方法。创建一个静态方法,它可以接受指向基类的引用,将其向下转型到导出类,然后再调用该静态方法。在main()中,展现它的运行情况。然后,为基类中的方法加上abstract声明,这样就不再需要进行向下转型。
package job;
import java.util.*;
abstract class A{
}
class B extends A{
void show(){
System.out.println("B is calling");
}
}
abstract class C{
abstract void show();
}
class D extends C{
@Override
void show() {
System.out.println("C is calling");
}
}
public class Main {
static void getshow(A a){
((B)a).show();//必须需要向下转型
}
static void getshow2(C c){
c.show();//不需要向下转型
}
public static void main(String[] args) {
A a=new B();
getshow(a);
C c=new D();
getshow2(c);
}
}
5.在某个包内创建一个接口,内含三个方法,然后在另一个包中实现此接口。
package Instrument;
/**
* @ClassName: A
* @Description: A
* @author: hszjj
* @date: 2019/7/18 9:01
*/
public interface A {
void show1();
void show2();
void show3();
}
package job;
import java.util.*;
import Instrument.*;
class B implements A{
@Override
public void show1() {
System.out.println("showing 1");
}
@Override
public void show2() {
System.out.println("showing 2");
}
@Override
public void show3() {
System.out.println("showing 3");
}
}
public class Main {
public static void main(String[] args) {
}
}
6.证明接口内所有方法都自动是public的。
能在包job里继承接口内的方法,证明原方法一定是public的。
7.修改第8章中的练习9,使Rodent成为一个接口。
package job;
import java.awt.*;
import java.util.*;
interface Rodent{
void bit();
}
class Mouse implements Rodent{
@Override
public void bit(){
System.out.println("Mouse bit");
}
}
class Gerbil implements Rodent{
@Override
public void bit(){
System.out.println("Gerbil bit");
}
}
class Hamster implements Rodent{
@Override
public void bit(){
System.out.println("Hamster bit");
}
}
public class Main {
public static void main(String[] args) {
Rodent[] a= {
new Mouse(),
new Gerbil(),
new Hamster(),
};
for(Rodent e:a){
e.bit();
}
}
}
注意:继承后方法要为public的,不然会报错!
8.在polymorphism.Sandwich.java中,创建接口FastFood并添加加合适的方法,然后修改Sandwich以实现FastFood接口。
我没找到原代码,不过做法应该也一样。
9.重构Music5.java,将在Wind,Precussion和Stringed中的公共方法移入一个抽象类中。
package job;
import java.util.*;
enum Note {
MIDDLE_C, C_SHARP, B_FLAT;
}
interface Instrument {
void play(Note n) ;
String toString() ;
void adjust() ;
}
class Wind implements Instrument {
public void play(Note n) {
System.out.println("Wind.play() " + n);
}
public String toString() {
return "Wind";
}
public void adjust() {
System.out.println("Adjusting Wind");
}
}
class Percussion implements Instrument {
public void play(Note n) {
System.out.println("Percussion.play() " + n);
}
public String toString() {
return "Percussion";
}
public void adjust() {
System.out.println("Adjusting Percussion");
}
}
class Stringed implements Instrument {
public void play(Note n) {
System.out.println("Stringed.play() " + n);
}
public String toString() {
return "Stringed";
}
public void adjust() {
System.out.println("Adjusting Stringed");
}
}
class Brass extends Wind {
public void play(Note n) {
System.out.println("Brass.play() " + n);
}
public void adjust() {
System.out.println("Adjusting Brass");
}
}
class Woodwind extends Wind {
public void play(Note n) {
System.out.println("Woodwind.play() " + n);
}
public String toString() {
return "Woodwind";
}
}
public class Main {
public static void tune(Instrument i) {
i.play(Note.MIDDLE_C);
}
public static void tuneAll(Instrument[] e) {
for (Instrument i : e) {
tune(i);
System.out.println(i);
}
}
public static void main(String[] args) {
// Upcasting during addition to the array:
Instrument[] orchestra = {
new Wind(),
new Percussion(),
new Stringed(),
new Brass(),
new Woodwind()
};
tuneAll(orchestra);
}
}
10.修改Music5.java,添加Playable接口。将play()的声明从Instrument中移动Playable中。通过将Playable包括在implements列表中,把Playable添加到导出类中。修改tune()使它接受Playable而不是Instrument作为参数。
package job;
import java.util.*;
enum Note {
MIDDLE_C, C_SHARP, B_FLAT;
}
interface Instrument {
String toString();
void adjust();
}
interface Playable{
void play(Note n) ;
}
class Wind implements Instrument,Playable {
public void play(Note n) {
System.out.println("Wind.play() " + n);
}
public String toString() {
return "Wind";
}
public void adjust() {
System.out.println("Adjusting Wind");
}
}
class Percussion implements Instrument,Playable {
public void play(Note n) {
System.out.println("Percussion.play() " + n);
}
public String toString() {
return "Percussion";
}
public void adjust() {
System.out.println("Adjusting Percussion");
}
}
class Stringed implements Instrument,Playable {
public void play(Note n) {
System.out.println("Stringed.play() " + n);
}
public String toString() {
return "Stringed";
}
public void adjust() {
System.out.println("Adjusting Stringed");
}
}
class Brass extends Wind {
public void play(Note n) {
System.out.println("Brass.play() " + n);
}
public void adjust() {
System.out.println("Adjusting Brass");
}
}
class Woodwind extends Wind {
public void play(Note n) {
System.out.println("Woodwind.play() " + n);
}
public String toString() {
return "Woodwind";
}
}
public class Main {
public static void tune(Playable i) {
i.play(Note.MIDDLE_C);
}
public static void tuneAll(Playable[] e) {
for (Playable i : e) {
tune(i);
System.out.println(i);
}
}
public static void main(String[] args) {
// Upcasting during addition to the array:
Playable[] orchestra = {
new Wind(),
new Percussion(),
new Stringed(),
new Brass(),
new Woodwind()
};
tuneAll(orchestra);
}
}
11.创建一个类,它有一个方法用于接受一个String类型的参数,生成的结果是将该参数中每一对字符进行互换。对该类进行适配,使得它可以用于interfaceprocessor.Apply.process()。
package job;
import java.util.*;
interface Processor {
String name();
Object process(Object input);
} ///:~
class B implements Processor{
@Override
public String name(){
return getClass().getPackageName();
}
@Override
public Object process(Object input){
return A.renew((String)input);
}
}
class Apply {
public static void process(Processor p, Object s) {
System.out.println("Using Processor " + p.name());
System.out.println(p.process(s));
}
}
class A{
static String renew(String s){
StringBuilder a=new StringBuilder(s);
for(int i=0;i<s.length()-1;i+=2){
char b=a.charAt(i);
char c=a.charAt(i+1);
a.setCharAt(i,c);
a.setCharAt(i+1,b);
}
return a.toString();
}
}
public class Main {
public static void main(String[] args) {
Apply.process(new B(),"abcde");
}
}
这里面有好多新知识,我一一列出来:TOST
1.StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
2.charAt,获取字符
3.setCharAt:字面意思
4.toString:可以直接使用通过“.”来调用
12.在Adventure.java中,按照其他接口的样式,增加一个CanClimb接口。
package job;
import java.util.*;
interface CanClimb{
void climb();
}
class Hero implements CanClimb{
public void climb(){
System.out.println("CLIMBING");
}
}
public class Main {
public static void c(CanClimb a){
a.climb();
}
public static void main(String[] args) {
Hero a=new Hero();
c(a);
}
}
13.创建一个接口,并从该接口继承两个接口,然后从后面两个接口多重继承第三个接口。
interface A{
void a();
}
class B implements A{
@Override
public void a() {
}
}
class C implements A{
@Override
public void a() {
}
}
class D extends B,C{//error
@Override
public void a() {
super.a();
}
}
原因:Java allows multiple interface inheritance but not multiple implementation inheritance, which eliminates ambiguity about which of two identical members we use when combining implementations of the same base class.
正确写法:
package job;
import java.util.*;
interface A{
void a();
}
interface B extends A{
@Override
public void a();
void c();
}
interface C extends A{
@Override
public void a();
void d();
}
class D implements B,C{//error
@Override
public void a() {
}
@Override
public void c() {
}
@Override
public void d() {
}
}
14.创建三个接口,每个接口都包含两个方法。继承出一个接口,它组合了这三个接口并添加了一个新方法。创建一个实现了该新接口并继承了某个具体类的类。现在编写四个方法,每一个方法接受这四个接口之一作为参数。在main()方法中,创建这个类的对象,并将其传递给这四个方法。
package job;
import java.util.*;
interface A{
void A1();
void A2();
void A3();
}
interface B{
void B1();
void B2();
void B3();
}
interface C{
void C1();
void C2();
void C3();
}
class D implements A,B,C{
@Override
public void A1() {
}
@Override
public void A2() {
}
@Override
public void A3() {
}
@Override
public void B1() {
}
@Override
public void B2() {
}
@Override
public void B3() {
}
@Override
public void C1() {
}
@Override
public void C2() {
}
@Override
public void C3() {
}
public void D(){
}
}
class E{
}
class F extends E{
D d=new D();
}
public class Main {
static void show1(Object obj){
}
static void show2(Object obj){
}
static void show3(Object obj){
}
static void show4(Object obj){
}
public static void main(String[] args) {
F f = new F();
show1(f);
show2(f);
show3(f);
show4(f);
}
}
说白了我没看懂他要干嘛,但是我照做了。
15.将前一个练习修改为:创建一个抽象类,并将其继承到一个导出类中。
package job;
import java.util.*;
abstract class A{
}
class B extends A{
}
public class Main {
public static void main(String[] args) {
}
}
还是没看懂,照做好了。
16.13章再说,没看懂。
17.证明在接口中的域隐式地是static和final的。
package job;
import java.util.*;
interface A{
int x=1;
}
public class Main {
public static void main(String[] args) {
System.out.println(A.x);
A.x=2;//Error:(10, 10) java: 无法为最终变量x分配值
}
}
18.创建一个Cycle接口及其Unicycle,Bicycle和Tricycle实现。对每种类型的Cycle都创建相应的工厂,然后编写代码使用这些工厂。
package job;
import java.util.*;
interface Cycle{
void run();
}
interface CycleFactory{
Cycle getCycle();
}
class Unicycle implements Cycle{
@Override
public void run() {
System.out.println("Unicycle Running");
}
}
class Bicycle implements Cycle{
@Override
public void run() {
System.out.println("Bicycle Running");
}
}
class Tricycle implements Cycle{
@Override
public void run() {
System.out.println("Tricycle Running");
}
}
class UnicycleCycleFactory implements CycleFactory{
@Override
public Cycle getCycle() {
return new Unicycle();
}
}
class BicycleCycleFactory implements CycleFactory{
@Override
public Cycle getCycle() {
return new Bicycle();
}
}
class TricycleCycleFactory implements CycleFactory{
@Override
public Cycle getCycle() {
return new Tricycle();
}
}
class Factory{
static void Consumer(CycleFactory fact){
Cycle c=fact.getCycle();
c.run();
}
}
public class Main {
public static void main(String[] args) {
Factory.Consumer(new UnicycleCycleFactory());
}
}
19.使用工厂方法来创建一个框架,它可以执行抛硬币和掷骰子功能。
package job;
import java.util.*;
interface Game{
void play();
void getresult();
}
interface GameFactory{
Game getGame();
}
class Coin implements Game{
Random rand=new Random();
int coin=0;
@Override
public void play() {
switch (rand.nextInt(2)) {
case 0:
coin = 0;
break;
case 1:
coin = 1;
break;
default:
}
}
public void getresult(){
if(coin==0){
System.out.println("硬币为正");
}
else{
System.out.println("硬币为反");
}
}
}
class CoinFactory implements GameFactory{
@Override
public Game getGame() {
return new Coin();
}
}
class Factories{
public static void PlayGame(GameFactory fact){
Game a=fact.getGame();
a.play();
a.getresult();
}
}
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Factories.PlayGame(new CoinFactory());
}
}
}
结束~
我的另一个博客:https://www.cnblogs.com/hsjj/
会不定时的更新算法题
有问题欢迎发送邮件至hpzhangjunjiell@163.com
我们下次见哦~