Java编程思想第四版第九章练习

本文通过多个示例讲解了Java中的抽象类和接口的使用方法,包括抽象类的定义、接口的应用、方法覆盖等内容,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这一章讲的是接口,

其中抽象和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
我们下次见哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值