Улучшение / с моего общего метода ввода консоли Java? - PullRequest
5 голосов
/ 19 июля 2010

Используя Java Generics, я попытался реализовать универсальный метод ввода с консоли.

public static <T> T readFromInput(String message, Class<?> c) throws Exception{
        System.out.println(message);
        Scanner scanner = new Scanner(System.in);
        try {
            if(c == Integer.class)
                return (T) Integer.valueOf(scanner.nextInt());
            if(c == String.class)
                return (T) scanner.nextLine();
            if(c == Double.class)
                return (T) Double.valueOf(scanner.nextDouble());
            if(c == Float.class)
                return (T) Float.valueOf(scanner.nextFloat());
        } catch (InputMismatchException e) {
            throw new Exception(e);
        }
        return null;
    }

У меня предупреждение "Тип безопасности: не проверено приведение от Integer к T"Кроме @SuppressWarnings, возможно ли избежать этого предупреждения?

Есть ли лучшие способы реализации моего метода?Заранее спасибо

Ответы [ 8 ]

7 голосов
/ 19 июля 2010

Вместо этого можно использовать метод Class#cast, но следует оставить некоторые комментарии, потому что даже если cast не создает предупреждение, оно может вызвать исключение ClassCastException во время выполнения, если приведение невозможно.

public static <T> T readFromInput(String message, Class<T> c) throws Exception{
    System.out.println(message);
    Scanner scanner = new Scanner(System.in);
    try {
        if(c == Integer.class)
            // the next cast to Integer is safe
            return c.cast(Integer.valueOf(scanner.nextInt()));
        if(c == String.class)
            // the next cast to String is safe
            return c.cast(scanner.nextLine());
        if(c == Double.class)
            // the next cast to Double is safe
            return c.cast(Double.valueOf(scanner.nextDouble()));
        if(c == Float.class)
            // the next cast to Float is safe
            return c.cast(Float.valueOf(scanner.nextFloat()));
    } catch (InputMismatchException e) {
        throw new Exception(e);
    }
    return null;
}

Обратите внимание, что я немного изменил сигнатуру метода - это должно быть Class<T>, а не Class<?>, чтобы гарантировать, что экземпляр Class соответствует параметру типа.

2 голосов
/ 19 июля 2010

Думаю, вы пытаетесь пере абстрагировать проблему. Что не так с этим?

    Scanner scanner = new Scanner(System.in);

    System.out.println("Give me a boolean:");
    boolean bool = scanner.nextBoolean();

    System.out.println("Give me an integer:");
    int integer = scanner.nextInt();

Приведение не требуется, и вам все равно придется обрабатывать исключение в любом случае ........

Помни, ПОЦЕЛУЙ, "Делай это просто глупо" ...

2 голосов
/ 19 июля 2010

Другие показали, как вы можете сделать это с Class.cast, но как это сделать?

Я предлагаю readInt, readString, readFloat и readDouble методы. Кроме того, я подозреваю, что Scanner может буферизовать, что может привести к неприятностям.

1 голос
/ 19 июля 2010

Сделай так:

public static <T> T readFromInput(String message, Class<T> c) throws Exception{
    System.out.println(message);
    Scanner scanner = new Scanner(System.in);
    try {
        if(c == Integer.class)
            return c.cast(scanner.nextInt());
        if(c == String.class)
            return c.cast(scanner.nextLine());
        if(c == Double.class)
            return c.cast(scanner.nextDouble());
        if(c == Float.class)
            return c.cast(scanner.nextFloat());
    } catch (InputMismatchException e) {
        throw new Exception(e);
    }
    return null;
}
0 голосов
/ 19 июля 2010

Вы можете избавиться от предупреждения, используя конкретный класс, который вы передаете для приведения объекта:

    public static <T> T readFromInput(String message, Class<T> c) throws Exception{
        ..
            return c.cast(Integer.valueOf(scanner.nextInt()));
        ..
    }

В этом случае я бы хотел реализовать несколько методов readFromInput, переопределенных вашими желаемыми типами, напримерpublic static Float readFromInput (строковое сообщение, класс c) public static Integer readFromInput (строковое сообщение, класс c) и т. д.

0 голосов
/ 19 июля 2010

Вы можете сделать следующее:

    public static <T> T readFromInput(String message, Class<T> c) throws Exception{ 
       System.out.println(message); 
       Scanner scanner = new Scanner(System.in); 
       try { 
           if(c == Integer.class) 
               return c.cast(scanner.nextInt()); 
           if(c == String.class) 
               return c.cast(scanner.nextLine()); 
           if(c == Double.class) 
               return c.cast(scanner.nextDouble()); 
           if(c == Float.class) 
               return c.cast(scanner.nextFloat()); 
       } catch (InputMismatchException e) { 
           throw new Exception(e); 
       } 
       return null; 
   } 

Однако я настоятельно рекомендую не бросать Exception. Создайте более конкретное исключение (либо исходное исключение времени выполнения, либо какое-либо соответствующее проверенное исключение).

0 голосов
/ 19 июля 2010

Нет общего способа избежать предупреждения "Unchecked cast", кроме использования @SuppressWarnings (unchecked) аннотации.

В конкретном случае вы получаете это предупреждение, потому что нет гарантии, что параметр Class<?> c может быть приведен к T, поскольку универсальные элементы Java проверяются только при компиляции, и никакие проверки не могут выполняться во время выполнения.

0 голосов
/ 19 июля 2010

Чтение из этого поста, Универсальная функция Java: как вернуть Универсальный тип Я избавился от предупреждения:

public static <T> T readFromInput(String message, Class<T> c) throws Exception{
        System.out.println(message);
        Scanner scanner = new Scanner(System.in);
        try {
            if(c == Integer.class)
                return c.cast(scanner.nextInt());
            if(c == String.class)
                return c.cast(scanner.nextLine());
            if(c == Double.class)
                return c.cast(scanner.nextDouble());
            if(c == Float.class)
                return c.cast(scanner.nextFloat());
        } catch (InputMismatchException e) {
            throw new Exception(e);
        }
        return null;
    }
...