【问题标题】:Reduce code duplication when reading different types of numbers from console从控制台读取不同类型的数字时减少代码重复
【发布时间】:2017-09-20 15:09:21
【问题描述】:

我创建了三个基本上做同样事情的方法 readLong、readInt 和 readDouble。唯一的区别是扫描仪调用的方法。如何通过将它们全部转换为一种方法来减少重复代码?

public long readLong(String description)
    {
        System.out.println(description);
        long nrToReturn = 0;
        boolean acceptedValue = false;

        do {
            System.out.println();
            System.out.print("Choose one: ");
            try
            {
                nrToReturn = consoleScanner.nextLong(); //Only line thats different except return value
                acceptedValue = true;
            }catch(Exception e)
            {
                acceptedValue = false;
                consoleScanner.nextLine();
            }
        }while (!acceptedValue);

        consoleScanner.nextLine();
        return nrToReturn;
    }

【问题讨论】:

  • code review上发布这个问题。
  • 看看Java中的泛型类型
  • 这些方法的调用者如何知道调用哪一个?
  • 我认为调用者知道调用哪一个,但问题是让一个方法 public static T readNumber(String description)
  • @Michu93 我试过了,但问题是泛型类型 T 不接受 Long。编译器 syes “Cannot cast long to T”。

标签: java console java.util.scanner


【解决方案1】:

这里我们有一个想法:

import java.util.Scanner;

public class ScannerTest {

    private Scanner consoleScanner;

    public ScannerTest() {
        consoleScanner = new Scanner(System.in);
    }

    @SuppressWarnings("unchecked")    
    private <T extends Number> T readType(String description, Class<T> desiredType) {
        System.out.println(description);
        Number result = null;

        while (result == null) {
            System.out.println();
            System.out.print("Choose one: ");
            try {
                if (Integer.class.equals(desiredType)) {
                    result = new Integer(consoleScanner.nextInt());
                } else if (Long.class.equals(desiredType)) {
                    result = new Long(consoleScanner.nextLong());
                }
            } catch(Exception e) {
                consoleScanner.nextLine();
            }
        }

        consoleScanner.nextLine();
        return (T) result;
    }

    public long readLong(String description) {
        return this.readType(description, Long.class);
    }

    public int readInt(String description) {
        return this.readType(description, Integer.class);
    }

    public static void main(String[] args) {
        ScannerTest t = new ScannerTest();
        t.readLong("Reading a long value...");
        t.readInt("Reading an integer value...");
    }  
}

更新,遵循@Michu93 单一透明方法的想法:

import java.util.Scanner;

public class ScannerTest {

    private Scanner consoleScanner;

    public ScannerTest() {
        consoleScanner = new Scanner(System.in);
    }

    @SuppressWarnings("unchecked")
    public <T extends Number> T readNumber(String description) {
        System.out.println(description);
        Number result = null;

        while (result == null) {
            System.out.print("\nChoose one: ");
            String textRead = consoleScanner.next();

            try {
                result = new Integer(textRead);
            } catch(Exception e1) {
                try {
                    result = new Long(textRead);
                } catch (Exception e2) {
                    try {
                        result = new Double(textRead);
                    } catch (Exception e3) {
                    }
                }
            }
            consoleScanner.nextLine();
        }

        return (T) result;
    }

    public static void main(String[] args) {
        ScannerTest t = new ScannerTest();
        for (int i = 0; i < 3; i++) {
            Number input = t.readNumber(i + ": Reading int, long or double...");
            System.out.println("Input class: " + input.getClass().getCanonicalName());
            System.out.println("Input value: " + input);
        }
    }  
}

【讨论】:

  • 编辑:正如@Michu93 指出的那样,我在考虑使用泛型而不是 Object 时也有同样的想法。但是我认为在不告知需要哪种类型的输入的情况下创建这样一个公共方法 [public static T readNumber(String description)] 是不可能的,除非您定义类型之间的层次结构并尝试读取每个每次调用方法时键入直到成功。更新了我的答案以适应 的想法。 [无法评论原始线程,因为我还不到 50 分,抱歉]。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-22
  • 2014-02-04
  • 2016-01-12
  • 1970-01-01
  • 2017-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多