简体   繁体   中英

Reduce code duplication when reading different types of numbers from console

I have created three methods readLong, readInt and readDouble that basically does the same thing. Only difference is the method called by a scanner. How can I reduce duplicate code by turning them all to one method?

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;
    }

Here we go with one idea:

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...");
    }  
}

Update , following @Michu93 idea of a single transparent method:

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);
        }
    }  
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM