konwersja łańcucha tekstowego do zadanej klasy

0

Tak jak w temacie; moje rozwiązanie nie jest najefektywniejsze, ale działa. Działa za wyjątkiem sytuacji, gdy jako argument 'to' podamy obiekt reprezentujący klasę typu podstawowego. Można to oczywiście zrobić dodając kolejne porównania,

... else if (to.getName().equalsIgnoreCase("int")) {
                return Integer.decode(from);

ale chyba jest jakiś prostszy/efektywny sposób na 'spakowanie' typu podstawowego w wersję obiektową??

private Object convertValue(String from, Class<?> to) {
        try {
            if (to.getName().equalsIgnoreCase(Boolean.class.getName())) {
                return Boolean.valueOf(from);
            } else if (to.getName().equalsIgnoreCase(Byte.class.getName())) {
                return Byte.decode(from);
            } else if (to.getName().equalsIgnoreCase(Short.class.getName())) {
                return Short.decode(from);
            } else if (to.getName().equalsIgnoreCase(Integer.class.getName())) {
                return Integer.decode(from);
            } else if (to.getName().equalsIgnoreCase(Long.class.getName())) {
                return Long.decode(from);
            } else if (to.getName().equalsIgnoreCase(Character.class.getName())) {
                return new Character(from.charAt(0));
            } else if (to.getName().equalsIgnoreCase(Float.class.getName())) {
                return new Float(Float.parseFloat(from));
            } else if (to.getName().equalsIgnoreCase(Double.class.getName())) {
                return new Double(Double.parseDouble(from));
            } else if (to.getName().equalsIgnoreCase(String.class.getName())) {
                return from;
            }
        } catch (Exception ex) {
            System.err.println(String.format("Nie można przekonwertować wartości '%s' na typ '%s'.", from, to.getSimpleName()));
            return null;
            //throw new RuntimeException(ex);
        }

        return null;
    }
0

Strasznie przekombinowane. Po pierwsze:

private <T> T convertValue(String from, Class<T> to) {
   try {
       if(to.getSupperclass == Number.class){
         return to.getClass().getConstructor(String.class).newInstance(from);
       }
       else if(to == Character.class && form.length > 0){
         return from.charAt(0);
       }
       else if(to == Byte.class && form.length > 0){
          return Byte.valueOf(0);
       }
   }
   cache(Exception e){
//reszta
   }
}

Problem z prymitywami jest poważniejszy, ale tylko na pierwszy rzut oka:

enum Primitives{
  private Class clazz;
  int(Integer.class);
  public Class getMappedClass(String s){
     // pobierz enum za pomocą metody valueOf(Primitives.class, s)
     return p.clazz;
  }
} 

To jest podpowiedź. Wystarczy zrobić mapowania dla klas prymitywów w postaci enuma, który potrafi zwracać wartość przez String.

0

Nie lepiej użyć mapy? O(1) niezależnie od liczby konwerterów.

private static interface Converter {
	Object convert(String from, Class<?> to) throws Exception;
};

private static Map<Class<?>, Converter> converters = new HashMap<Class<?>, Converter>();
{
	converters.put(Number.class, new Converter() {
		public Object convert(String from, Class<?> to) throws Exception {
			return to.getConstructor(String.class).newInstance(from);
		}
	});

	converters.put(Character.class, new Converter() {
		public Object convert(String from, Class<?> to) throws Exception {
			if (from.isEmpty()) {
				throw new IllegalArgumentException("String is empty");
			}

			return from.charAt(0);
		}
	});
}

public static Object convert(String from, Class<?> to) throws Exception {
	Class<?> superTo = to;
	while (superTo != null && !converters.containsKey(superTo)) {  /* Szukanie najlepszego dostepnego konwertera */
		superTo = superTo.getSuperclass();
	}

	Converter converter = converters.get(superTo);
	if (converter == null) {
		throw new IllegalArgumentException("Converter not supported");
	}

	return converter.convert(from, to);
}
0
Koziołek napisał(a)

Problem z prymitywami jest poważniejszy, ale tylko na pierwszy rzut oka:

enum Primitives{
  private Class clazz;
  int(Integer.class);
  public Class getMappedClass(String s){
     // pobierz enum za pomocą metody valueOf(Primitives.class, s)
     return p.clazz;
  }
} 

To się nawet nie skompiluje. "int" to nazwa zastrzeżona.

Jeżeli by się uprzeć to można to zrobić następująco: (tylko nie wiem w jakim celu, przecież można wszystko wsadzić do jednego słownika)

enum Primitives {
	INT(Integer.class);

	Primitives(Class<?> clazz) {
		this.clazz = clazz;
	}

	private final Class<?> clazz;

	public Class<?> getMappedClass(String s) {
		return valueOf(Primitives.class, s.toUpperCase()).clazz;
	}
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1