I'm having some trouble understanding the validation library, io.vavr.control.Validation. At the risk of asking too broad a question, I do have several sub-questions—however I believe they are closely related and would piece together to help me understand the proper way to use this validation mechanism.
I started with the example here: https://softwaremill.com/javaslang-data-validation.
Validation<String, ValidRegistrationRequest> validate(RegistrationRequest request) {
return combine(
validateCardId(request.getCardId()),
validateTicketType(request.getTicketType()),
validateGuestId(request.getGuestId())
)
.ap(ValidRegistrationRequest::new)
.mapError(this::errorsAsJson);
}
private Validation<String, Card> validateCardId(String cardId) {
// validate cardId
// if correct then return an instance of entity the cardId corresponds to
}
private Validation<String, TicketType> validateTicketType(String ticketType) {
// validate ticketType
// if known then return enumeration representing the ticket
}
private Validation<String, Guest> validateGuest(String guestId) {
// validate guestId
// if correct then return an instance of entity the questId corresponds to
}
At first, I didn't understand where the generic parameters for Validation<String, ValidRegistrationRequest> came from. I now understand that they are linked to the return types of the methods passed to mapError and ap, respectively. But:
How does combine know to return Validation<String, ValidRegistrationRequest>? I feel the only way this is possible, is if combine is actually a Validation<String, ValidRegistrationRequest>::combine, so that the ap and mapError are defined from this template. But I don't believe that the compiler should be able to imply that that combine refers to a static implementation in the class of the return type. What's happening here?
[Minor] What is the use case for using a ValidRegistrationRequest as opposed to just RegistrationRequest again? I'm tempted to do the latter in my coding, until I see an example.
A second example I was reading about is here: http://www.vavr.io/vavr-docs/#_validation.
class PersonValidator {
private static final String VALID_NAME_CHARS = "[a-zA-Z ]";
private static final int MIN_AGE = 0;
public Validation<Seq<String>, Person> validatePerson(String name, int age) {
return Validation.combine(validateName(name), validateAge(age)).ap(Person::new);
}
private Validation<String, String> validateName(String name) {
return CharSeq.of(name).replaceAll(VALID_NAME_CHARS, "").transform(seq -> seq.isEmpty()
? Validation.valid(name)
: Validation.invalid("Name contains invalid characters: '"
+ seq.distinct().sorted() + "'"));
}
private Validation<String, Integer> validateAge(int age) {
return age < MIN_AGE
? Validation.invalid("Age must be at least " + MIN_AGE)
: Validation.valid(age);
}
}
Where did Seq come from? Is that the default when no mapError is supplied? But I'm looking at the decompiled .class file for Validation.class, and the only reference to Seq is here:
static <E, T> Validation<List<E>, Seq<T>> sequence(Iterable<? extends Validation<List<E>, T>> values) {
Objects.requireNonNull(values, "values is null");
List<E> errors = List.empty();
List<T> list = List.empty();
Iterator var3 = values.iterator();
while(var3.hasNext()) {
Validation<List<E>, T> value = (Validation)var3.next();
if (value.isInvalid()) {
errors = errors.prependAll(((List)value.getError()).reverse());
} else if (errors.isEmpty()) {
list = list.prepend(value.get());
}
}
return errors.isEmpty() ? valid(list.reverse()) : invalid(errors.reverse());
}
Which, I don't think is relevant. Perhaps I'm using an outdated Validation? (It is after all javaslang.control.Validation in my imports, not io.vavr.control.Validation.)
I had this question for both examples: How does combine know which parameters to pass to the constructor (ap), and in what order? Is the answer, "All its parameters, in the order given"?
Thanks in advance.
You have the same questions and doubts I had when was looking for the first time into validation mechanism of Vavr.
Here are my responses to the first two questions:
combine(...) method returns with an instance of a validation builder, in this case, this is a Builder3 class holding three results of validate*(...) functions. The ap(...) method is a method of this builder and triggers building of Validation instance.
When it is called, validation results are applied, one by one, to a curried version of a function provided as an argument:
v3.ap(v2.ap(v1.ap(Validation.valid(f.curried()))))
In the example, f is a constructor of ValidRegistrationRequest class. In the end, we have a validation holding the valid request instance.
On the other hand, if any of the results are invalid, the method creates an invalid result with a list of error messages. And calling mapError(this::errorsAsJson) (on Validation instance this time!) transforms it into a JSON format.
What's the use case of using ValidRegistrationRequest?
I have used Vavr's validation in one of my projects. I had a request coming with some identifiers of entities. To validate the correctness of it, I had to query a database to check whether there is something for each id.
So, if validation returned with the original request, I would have to fetch those objects from the database once again. Thus, I decided to return ValidRegistrationRequest holding domain objects. With calling database once only, request processing is significantly faster.
And answers to the second pair of questions:
Yes, you are right. In case of an invalid result, Validation.combine(...).ap(...) returns with an instance of Invalid class, holding a list of error messages, returned from validation methods.
If you look into sources, to Validation.ap(...) method, you can see that invalid results are gathered into a Vavr's List. Because it inherits from Seq, you can see this type in the validatePerson example Seq<String>.
Yes, exactly. "All its parameters, in the order given" :)
The order of arguments in combine must be the same as the order of arguments taken by the function provided to ap(...) method.
With sources downloaded, it is way easier to track internals of Vavr.
Okay, this is my attempt at answering my own questions, but confirmation from someone more experienced would be nice. I found the latest source for Validation here.
Example 1
The article I copied the example from actually stated that combine was "statically imported for better readability." I missed that. So, I was right—we are calling a static method. Specifically, this one:
static <E, T1, T2, T3> Builder3<E, T1, T2, T3> combine(Validation<E, T1> validation1, Validation<E, T2> validation2, Validation<E, T3> validation3) {
Objects.requireNonNull(validation1, "validation1 is null");
Objects.requireNonNull(validation2, "validation2 is null");
Objects.requireNonNull(validation3, "validation3 is null");
return new Builder3<>(validation1, validation2, validation3);
}
My guess at the use of ValidRegistrationRequest is simply to enforce validation at compile-time. That is, this way, a developer can never accidentally use an unvalidated RegistrationRequest if all consuming code require a ValidRegistrationRequest.
Example 2
I think the Set comes from here:
/**
* An invalid Validation
*
* #param <E> type of the errors of this Validation
* #param <T> type of the value of this Validation
*/
final class Invalid<E, T> implements Validation<E, T>, Serializable {
...
#Override
public Seq<E> getErrors() {
return errors;
}
...
}
And then something to do with this:
/**
* Applies a given {#code Validation} that encapsulates a function to this {#code Validation}'s value or combines both errors.
*
* #param validation a function that transforms this value (on the 'sunny path')
* #param <U> the new value type
* #return a new {#code Validation} that contains a transformed value or combined errors.
*/
#SuppressWarnings("unchecked")
default <U> Validation<E, U> ap(Validation<E, ? extends Function<? super T, ? extends U>> validation) {
Objects.requireNonNull(validation, "validation is null");
if (isValid()) {
return validation.map(f -> f.apply(get()));
} else if (validation.isValid()) {
return (Validation<E, U>) this;
} else {
return invalidAll(getErrors().prependAll(validation.getErrors()));
}
}
#mchmiel answered my question while I was writing mine.
Related
I came across a piece of code where two methods have very similar functionalities, return the same type, but are different.
private Set<String> extractDeviceInfo(List<Device> devices){
Set<String> sets= new HashSet<>();
for(Device item:items){
sets.add(item.getDeviceName());
}
return sets;
}
private Set<String> extractDeviceInfoFromCustomer(List<Customer> customers){
Set<String> sets= new HashSet<>();
for (Customer c : customers) {
sets.add(c.getDeviceName());
}
return sets;
}
As you can see from the code above, both methods are returning the same Set and retrieving the same data.
I'm trying to attempt to create a generic method out of it and did some research but couldn't find anything that could solve this issue.
If I understand this correctly, using generics, I can define generic parameters in the method and then pass parameters as well as the class type when calling the method. However I am not sure what to do after wards.
For example, the method getDeviceName() how can I call it out of a generic class as the compiler doesn't know whether the generic class has that method or not.
I will really appreciate if someone could tell me whether this is possible and how to achieve the desired result.
Thanks
UPDATE: Creating an interface and then having implementation looks like a good solution but I feel like it's overdoing when it comes to refactoring a couple of methods to avoid boiler plate.
I've noticed that Generic classes can be passed as a parameter and the have methods like getMethod() etc.
I was wondering if it was possible to create a generic method where you pass the class as well as the method name and then the method resolves that at runtime
eg.
private <T> Set<String> genericMethod(Class<T> clazz, String methodName ){
clazz.resolveMethod(methodName);
}
So basically, I could do this when calling the method:
genericMethod(Customer.class,"gedDeviceInfo");
I believe there's one language where this was achievable but not sure if you can do it in Java, although, a few years back I remember reading about resolving string into java code so they get compiled at runtime.
Both Device and Customer should implement the same interface where the method getDeviceName is defined:
interface Marker {
String getDeviceName();
}
class Device implements Marker { ... }
class Customer implements Marker { ... }
I named it Marker, but it's up to you to name it reasonably. Then, the method might look like:
private Set<String> extractDeviceInfo(List<? extends Marker> markers) {
return markers.stream().map(Marker::getDeviceName).collect(Collectors.toSet());
}
It allows the next type variations:
extractDeviceInfo(new ArrayList<Device>());
extractDeviceInfo(new ArrayList<Customer>());
extractDeviceInfo(new ArrayList<Marker>());
99% of the time Andrew answer is the solution. But, another approach is to define the function in parameter.
This can be useful for some reporting or if you need to be able to extract values from an instance in multiple ways using the same method.
public static <T, U> Set<U> extractInfo(List<T> data, Function<T, U> function){
return data.stream().map(function).collect(Collectors.toSet());
}
Example :
public class Dummy{
private String a;
private long b;
public Dummy(String a, long b){ this.a = a; this.b = b; }
public String getA(){return a; }
public long getB(){return b; }
}
List<Dummy> list = new ArrayList<>();
list.add(new Dummy("A1", 1));
list.add(new Dummy("A2", 2));
list.add(new Dummy("A3", 3));
Set<String> setA = extractInfo(list, Dummy::getA); // A1, A2, A3
Set<Long> setB = extractInfo(list, Dummy::getB); // 1, 2, 3
using reflection in java will take a performance hit. in your case, it's probably not worth it.
There is nothing wrong with your original code, if there are less than 3 places using it, DO NOT refactor. If there is more than 3 places and expecting more coming, you can refactor using #andrew's method.
you should not refactor code just for the sake of refactoring in my opinion.
I saw some example of of using supplier interface at https://dzone.com/articles/supplier-interface.
My question is, if in the above example I could do something as easy as :
driveVehicle(new Vehicle());
driveVehicle(new Car());
Why would one want to use supplier interface, if all it does is call a method, without taking in any parameters.
Suppose you have parameters stored in database that you want to keep in constant all over your app
// Assume retrieveSystemParameter query database which allows to change parameters
public static String SYSTEM_PARAMETER = StaticUtilities.retrieveSystemParameter();
That value will be initialized once and won't change untill a redeployment. That being said, if instead you use a supplier :
public static Supplier<String> SYSTEM_PARAMETER_SUPPLIER = StaticUtilities::retrieveSystemParameter;
When you need the value somewhere you will call SYSTEM_PARAMETER_SUPPLIER.get() which will retrieve parameter in the database when needed - that way if you change a parameter in database, you won't have to redeploy.
As you can see, Suppliers are lazy. They do the work when you ask them to work (by calling .get()) - that may allow you some performance gain if you deal with them wisely. Sometimes you will call a method which expect a variable X passing in method retrieveX and then end up not needing X in the method because some conditions were not met. In that case you will lose performance as you will execute the code to retrieve X while a supplier that retrieve X would only execute it when calling .get and you would only do that call if the conditions were met.
Disclaimer : the system parameter constant is just the first example that came to my mind, but considering it query the database on each .get() you'd rather cache the parameter and have the cache call .get() at a specific interval.
I guess Optional might be perfect example. Consider the following snippet:
final Product firstProduct = Optional.ofNullable(product)
.orElse(productDao.findProductById(id));
final Product secondProduct = Optional.ofNullable(product)
.orElseGet(() -> productDao.findProductById(id));
You're getting a product that may be null. In order to determine firstProduct java will have to call expression in orElse method so no matter product is null or not you always have to determine value that will be returned in case product is null.
In order to determine secondProduct database doesn't have to be queried in case product is not null because you're passing a Supplier that will be called only if product is null.
Another example is when your method that accepts a supplier is not pure (i.e., it has side effect), and the side effect happens before calling the lambda, and the behaviour of the lambda is affected by the side effect.
Consider, for instance, this example:
public class TestClass {
private String field;
public String getField() {
return field;
}
public void method(Supplier<String> supplier) {
field = "This is";
System.out.println(supplier.get() + " a test");
}
public static void main(String[] args) {
TestClass c = new TestClass();
c.method(() -> c.getField());
}
}
Here, method() is not pure, as it changes the value of field, which is used later in the lambda (through calling the getField() method). As the lambda is called in place (i.e., when get() is called), calling getField() will happen after setting the field. In other words, method() accepts a Supplier<String> instead of a String in an attempt to let the clients safely call the getField() method.
Of course, having side effects should be avoided wherever possible, and this is just a toy example, but it shows a potential place where a supplier can be used.
Supplier adds one more level of indirection.
Given that "All problems in computer science can be solved by another level of indirection", it's likely that there are some problems that can be solved by using a Supplier.
Beware, however, of the corollary "...except for the problem of too many layers of indirection."
So, if there's no problem to solve, then Supplier is overkill and you should stick to directly invoking new.
Put differently: mistrust any "pattern" or "best practice" that doesn't start by explaining a problem (your question shows, you actually do mistrust, so just keep on asking this kind of questions).
I use it to avoid the unnecessary creation of additional states:
private Supplier<Boolean> detach = () -> false;
private Supplier<Boolean> isAttached = () -> false;
private Supplier<Integer> index = () -> null;
private final Function<List<ObserverWrapper<X, Y>>, Boolean> attachFun = observers -> {
isAttached = () -> observers.contains(this);
detach = () -> observers.remove(this);
index = () -> observers.indexOf(this);
return observers.add(this);
};
public boolean attach(List<ObserverWrapper<X, Y>> observers) {
return attachFun.apply(observers);
}
public boolean isAttached() {
return isAttached.get();
}
public Integer observerIndex() {
return index.get();
}
Which some would say is unnecessary in itself, but then it becomes a philosophical problem.
A problem which would not exist if computers didn't exist, and then it becomes a real world problem of indirection.
I may admit that suppliers for me may have become an addiction, but in my mind they feel like the natural extrapolation and extension of all the programming axioms and principles.
You could use a Supplier in a map based factory class
public class StackService {
final static String INTEGERS = "Integers";
final static String DOUBLES = "Doubles";
final static String STRINGS = "Strings";
final static Map<String, Supplier<Stack>> stackType;
static {
stackType = new HashMap<>();
stackType.put(INTEGERS, Stack<Integer>::new);
stackType.put(DOUBLES, Stack<Double>::new);
stackType.put(STRINGS, Stack<String>::new);
}
public Stack<?> createStackOfType(String stackType) {
return stackType.get(stackType).get();
}
}
Here if you were to just use new Stack() you would be returning a reference to the same object rather than a new one.
How do I write a static method in Java that will take a List, perform an action on each element, and return the result (without affecting the original of course)?
For example, if I want to add 2 to each element what goes in the ... here? The concrete return type must be the same, e.g. if my List is a LinkedList with values 1,2,3 I should get back a LinkedList with values 3,4,5. Similarly for ArrayList, Vector, Stack etc, which are all Lists.
I can see how to do this using multiple if (lst instanceof LinkedList) ... etc... any better way?
import java.util.List;
public class ListAdd {
static List<Integer> add2 (List<Integer> lst) {
...
return result;
}
}
There are already many answers, but I'd like to show you a different way to think of this problem.
The operation you want to perform is known as map in the world of functional programming. It is something we do really all the time in functional languages.
Let M<A> be some kind of container (in your case, M would be List, and A would be Integer; however, the container can be lots of other things). Suppose you have a function that transforms As into Bs, that is, f: A -> B. Let's write this function as of type F<A, B>, to use a notation closer to Java. Note that you can have A = B, as in the example you give (in which A = B = Integer).
Then, the operation map is defined as follows:
M<B> map(M<A>, F<A, B>)
That is, the operation will return a M<B>, presumably by applying F<A, B> to each A in M<A>.
In practice...
There's a brilliant library developed by Google, called Guava, which brings lot's of functional idioms to Java.
In Guava, the map operation is called transform, and it can operate on any Iterable. It has also more specific implementations that work directly on lists, sets, etc.
Using Guava, the code you want to write would look like this:
static List<Integer> add2(List<Integer> ns) {
return Lists.transform(ns, new Function<Integer, Integer>() {
#Override Integer apply(Integer n) { return n + 2; }
}
}
Simple as that.
This code won't touch the original list, it will simply provide a new list that calculates its values as needed (that is, the values of the newly created list won't be calculated unless needed -- it's called a lazy operation).
As a final consideration, it is not possible for you to be absolutely sure that you will be able to return exactly the same implementation of List. And as many others pointed out, unless there's a very specific reason for this, you shouldn't really care. That's why List is an interface, you don't care about the implementation.
Fundamentally, the List interface doesn't make any guarantees that you'll have a way to duplicate it.
You may have some luck with various techniques:
Using clone() on the passed in List, although it may throw, or (since it is protected in Object) simply not be accessible
Use reflection to look for a public no-argument constructor on the passed-in List
Try to serialize and deserialize it in order to perform a "deep clone"
Create some sort of factory and build in knowledge of how to duplicate each different kind of List your code may encounter (What if it's a wrapper created by unmodifiableList(), or some oddball custom implementation backed by a RandomAccessFile?)
If all else fails, either throw, or return an ArrayList or a Vector for lack of better options
You could use reflection to look for a public zero-arg constructor on the result of lst.getClass() and then invoke() it to obtain the List into which you'll place your results. The Java Collections Framework recommends that any derivative of Collection offer a zero-arg constructor. That way, your results we be of the same runtime class as the argument.
Here is a variant which does neither copies nor modifies the original list. Instead, it wraps the original list by another object.
public List<Integer> add2(final List<Integer> lst) {
return new AbstractList<Integer>() {
public int size() {
return lst.size();
}
public Integer get(int index) {
return 2 + lst.get(index);
}
};
}
The returned list is not modifiable, but will change whenever the original list changes.
(This implements the iterator based on index access, thus it will be slow for a linked list. Then better implement it based on AbstractSequentialList.)
Of course, the resulting list will obviously not be of the same class as the original list.
Use this solution only if you really only need a read-only two added view of your original list, not if you want a modified copy with similar properties.
The whole point of using an interface, in this case List, is to abstract the fact that the implementation is hidden behind the interface.
Your intention is clear to me, however: the Clonable interface supports creating a new instance with the same state. This interface might not be defined on your List.
Often it's a good idea to rethink this situation: why do you need to clone the List in this place, this class? Shouldn't your list-creator be responsible for cloning the list? Or shouldn't the caller, who knows the type, make sure he passes in a clone of his list?
Probably, if you look for the semantics as you defined it, you can implement all your supported Lists:
static Vector<Integer> addTwo(Vector<Integer> vector) {
Vector<Integer> copy = null; // TODO: copy the vector
return addTwo_mutable(copy);
}
static ArrayList<Integer> addTwo(ArrayList<Integer> aList) {
ArrayList<Integer> copy = null; // TODO: copy the array list
return addTwo_mutable(copy);
}
static LinkedList<Integer> addTwo(LinkedList<Integer> lList) {
LinkedList<Integer> copy = null; // TODO: copy the linked list
return addTwo_mutable(copy);
}
private <T extends List<Integer>> static T addTwo_mutable(T list) {
return list; // TODO: implement
}
Even, when you don't support a data-type, you'll get a nice compiler error that the specified method does not exists.
(code not tested)
Just to show you that what you want to do is not possible in the general case, consider the following class:
final class MyList extends ArrayList<Integer> {
private MyList() {
super.add(1);
super.add(2);
super.add(3);
}
private static class SingletonHolder {
private static final MyList instance = new MyList();
}
public static MyList getInstance() {
return SingletonHolder.instance;
}
}
It is a singleton (also, a lazy, thread-safe singleton by the way), it's only instance can be obtained from MyList.getInstance(). You cannot use reflection reliably (because the constructor is private; for you to use reflection, you'd have to rely on proprietary, non-standard, non-portable APIs, or on code that could break due to a SecurityManager). So, there's no way for you to return a new instance of this list, with different values.
It's final as well, so that you cannot return a child of it.
Also, it would be possible to override every method of ArrayList that would modify the list, so that it would be really an immutable singleton.
Now, why would you want to return the exact same implementation of List?
OK well someone mentioned reflection. It seems to be an elegant solution:
import java.util.*;
public class ListAdd {
static List<Integer> add2 (List<Integer> lst) throws Exception {
List<Integer> result = lst.getClass().newInstance();
for (Integer i : lst) result.add(i + 2);
return result;
}
}
Concise, but it thows an checked exception, which is not nice.
Also, wouldn't it be nicer if we could use the method on concrete types as well, e.g. if a is an ArrayList with values 1, 2, 3, we could call add2(a) and get an ArrayList back? So in an improved version, we could make the signature generic:
static <T extends List<Integer>> T add2 (T lst) {
T res;
try {
res = (T) lst.getClass().newInstance();
} catch (InstantiationException e) {
throw new IllegalArgumentException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
for (Integer i : lst) res.add(i + 2);
return res;
}
I think throwing a runtime exception is the least worst option if a list without a nullary construcor is passed in. I don't see a way to ensure that it does. (Java 8 type annotations to the rescue maybe?) Returning null would be kind of useless.
The downside of using this signature is that we can't return an ArrayList etc as the default, as we could have done as an alternative to throwing an exception, since the return type is guaranteed to be the same type as that passed in. However, if the user actually wants an ArrayList (or some other default type) back, he can make an ArrayList copy and use the method on that.
If anyone with API design experience reads this, I would be interested to know your thoughts on which is the preferable option: 1) returning a List that needs to be explicity cast back into the original type, but enabling a return of a different concrete type, or 2) ensuring the return type is the same (using generics), but risking exceptions if (for example) a singleton object without a nullary constructor is passed in?
For example, I have a method that looks through a string for data separated by a specified deliminator, but some items might be a names, and other items might be numbers.
If a user calls my method to return item number X from the deliminated list, i want it to return a string if item X is a name, or a double if item X is a number.
For example, objectName.get(5); would get the 5th item in the deliminated list.
Would I have to use some type of overloading for this?
Or would I have to instead do something like objectName.getDouble(5); and objectName.getString(5); based on the fact that the user knows what item 5 is?
But what if the user doesn't know what item 5 is? He just needs a String or a Double depending on what it happens to be.
Here's one way to do this:
public Object get() {
if (blueMoon) {
return new Double(42.0);
} else {
return "fred";
}
}
Note that this will return a Double wrapper rather than a double.
I don't think this is a good idea though, since the caller now has to test the type of the returned value and do a typecast to do something with it.
For the record, Java does not allow a method to return a String or double because these types do not have a common supertype in the Java type system.
For this sort of thing, I prefer to use something akin to the Maybe/Option pattern from the functional programming camp. You end up with an interface like:
public abstract class DoubleOrString
{
// Constraint isDouble() xor isString()
public boolean isDouble();
public boolean isString();
//Must throw iff !isString()
public String getString();
//Must throw iff !ifDouble()
public Double getDouble();
public static DoubleOrString wrap(final double wrapMe)
{
return new DoubleOrString()
{
public boolean isDouble() {return true;}
public boolean isString() {return false;}
public Double getDouble() {return wrapMe;}
public String getString() {throw new RuntimeException();}
};
}
//same for wrap(String)
}
This forces the issue for clients, in that there is always a sanity check that there was indeed a double or String at the appropriate time. In your case, I'd make just one get() method, so when the client (thinks they) knows what the type is, the call is
objectName.get(5).getString();
and in your get(int) method, rather than returning a String or a double, the return statement looks like
DoubleOrString.wrap(theThingToReturn)
It's a little extra work up front, but it has paid of for me several times in the past.
Here's how you'd use it to build one (warning - this hasn't been near a compiler)
public static DoubleOrString parseADoubleOrString(String input) {
try {
return DoubleOrString.wrap(Integer.parseInt(input))
} catch (NumberFormatException nfe) {
return DoubleOrString.wrap(input);
}
}
and here's what the client looks like
String input = //get the input from the user somehow
DoubleOrString parsed = parseADoubleOrString(input);
if (parsed.isDouble())
aFunctionThatTakesADouble(parsed.getDouble());
else
aFunctionThatTakesAString(parsed.getString());
If you need to do this then there is problem with your design. Since the original datasource is String you have to accept that all returned values will be string and leave it to the client to check whether the result can be converted to a number.
If you want to save the client from doing the check, you can provide him with a minimal API which may look something like:
public class ValueExtractor {
public ValueExtractor(String delimitedText) {
// ...
}
/**
* Determines whether there is a next element
* to be returned
*/
public boolean next() {
// ...
}
public String get() {
// ...
}
/**
* Returns the value as a Double if possible
* null otherwise.
*/
public Double getPossibleDouble() {
// ...
}
}
The Java language does not expose an overload on the return type of a method. (As Thilo pointed out, this is a restriction of the Java language and not the JVM/bytecode.)
Generally this type of thing does not fit well into the Java type system. One could imagine returning an Either<String,Double> type (a more restricted return type than Object as suggested by Stephen C and a more general type than DoubleOrString as pointed out by B. Bear), but the general effort required to use such a construct in Java generally results in simply having multiple methods, e.g. getString(...) and getDouble(...).
I would like to do dynamic casting for a Java variable, the casting type is stored in a different variable.
This is the regular casting:
String a = (String) 5;
This is what I want:
String theType = 'String';
String a = (theType) 5;
Is this possible, and if so how? Thanks!
Update
I'm trying to populate a class with a HashMap that I received.
This is the constructor:
public ConnectParams(HashMap<String,Object> obj) {
for (Map.Entry<String, Object> entry : obj.entrySet()) {
try {
Field f = this.getClass().getField(entry.getKey());
f.set(this, entry.getValue()); /* <= CASTING PROBLEM */
} catch (NoSuchFieldException ex) {
log.error("did not find field '" + entry.getKey() + '"');
} catch (IllegalAccessException ex) {
log.error(ex.getMessage());
}
}
}
The problem here is that some of the class' variables are of type Double, and if the number 3 is received it sees it as Integer and I have type problem.
Yes it is possible using Reflection
Object something = "something";
String theType = "java.lang.String";
Class<?> theClass = Class.forName(theType);
Object obj = theClass.cast(something);
but that doesn't make much sense since the resulting object must be saved in a variable of Object type. If you need the variable be of a given class, you can just cast to that class.
If you want to obtain a given class, Number for example:
Object something = new Integer(123);
String theType = "java.lang.Number";
Class<? extends Number> theClass = Class.forName(theType).asSubclass(Number.class);
Number obj = theClass.cast(something);
but there is still no point doing it so, you could just cast to Number.
Casting of an object does NOT change anything; it is just the way the compiler treats it.
The only reason to do something like that is to check if the object is an instance of the given class or of any subclass of it, but that would be better done using instanceof or Class.isInstance().
Update
according your last update the real problem is that you have an Integer in your HashMap that should be assigned to a Double. What you can do in this case, is check the type of the field and use the xxxValue() methods of Number
...
Field f = this.getClass().getField(entry.getKey());
Object value = entry.getValue();
if (Integer.class.isAssignableFrom(f.getType())) {
value = Integer.valueOf(((Number) entry.getValue()).intValue());
} else if (Double.class.isAssignableFrom(f.getType())) {
value = Double.valueOf(((Number) entry.getValue()).doubleValue());
} // other cases as needed (Long, Float, ...)
f.set(this, value);
...
(not sure if I like the idea of having the wrong type in the Map)
You'll need to write sort of ObjectConverter for this. This is doable if you have both the object which you want to convert and you know the target class to which you'd like to convert to. In this particular case you can get the target class by Field#getDeclaringClass().
You can find here an example of such an ObjectConverter. It should give you the base idea. If you want more conversion possibilities, just add more methods to it with the desired argument and return type.
Regarding your update, the only way to solve this in Java is to write code that covers all cases with lots of if and else and instanceof expressions. What you attempt to do looks as if are used to program with dynamic languages. In static languages, what you attempt to do is almost impossible and one would probably choose a totally different approach for what you attempt to do. Static languages are just not as flexible as dynamic ones :)
Good examples of Java best practice are the answer by BalusC (ie ObjectConverter) and the answer by Andreas_D (ie Adapter) below.
That does not make sense, in
String a = (theType) 5;
the type of a is statically bound to be String so it does not make any sense to have a dynamic cast to this static type.
PS: The first line of your example could be written as Class<String> stringClass = String.class; but still, you cannot use stringClass to cast variables.
You can do this using the Class.cast() method, which dynamically casts the supplied parameter to the type of the class instance you have. To get the class instance of a particular field, you use the getType() method on the field in question. I've given an example below, but note that it omits all error handling and shouldn't be used unmodified.
public class Test {
public String var1;
public Integer var2;
}
public class Main {
public static void main(String[] args) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
map.put("var1", "test");
map.put("var2", 1);
Test t = new Test();
for (Map.Entry<String, Object> entry : map.entrySet()) {
Field f = Test.class.getField(entry.getKey());
f.set(t, f.getType().cast(entry.getValue()));
}
System.out.println(t.var1);
System.out.println(t.var2);
}
}
You can write a simple castMethod like the one below.
private <T> T castObject(Class<T> clazz, Object object) {
return (T) object;
}
In your method you should be using it like
public ConnectParams(HashMap<String,Object> object) {
for (Map.Entry<String, Object> entry : object.entrySet()) {
try {
Field f = this.getClass().getField(entry.getKey());
f.set(this, castObject(entry.getValue().getClass(), entry.getValue()); /* <= CASTING PROBLEM */
} catch (NoSuchFieldException ex) {
log.error("did not find field '" + entry.getKey() + '"');
} catch (IllegalAccessException ex) {
log.error(ex.getMessage());
}
}
}
It works and there's even a common pattern for your approach: the Adapter pattern. But of course, (1) it does not work for casting java primitives to objects and (2) the class has to be adaptable (usually by implementing a custom interface).
With this pattern you could do something like:
Wolf bigBadWolf = new Wolf();
Sheep sheep = (Sheep) bigBadWolf.getAdapter(Sheep.class);
and the getAdapter method in Wolf class:
public Object getAdapter(Class clazz) {
if (clazz.equals(Sheep.class)) {
// return a Sheep implementation
return getWolfDressedAsSheep(this);
}
if (clazz.equals(String.class)) {
// return a String
return this.getName();
}
return null; // not adaptable
}
For you special idea - that is impossible. You can't use a String value for casting.
Your problem is not the lack of "dynamic casting". Casting Integer to Double isn't possible at all. You seem to want to give Java an object of one type, a field of a possibly incompatible type, and have it somehow automatically figure out how to convert between the types.
This kind of thing is anathema to a strongly typed language like Java, and IMO for very good reasons.
What are you actually trying to do? All that use of reflection looks pretty fishy.
Don't do this. Just have a properly parameterized constructor instead. The set and types of the connection parameters are fixed anyway, so there is no point in doing this all dynamically.
For what it is worth, most scripting languages (like Perl) and non-static compile-time languages (like Pick) support automatic run-time dynamic String to (relatively arbitrary) object conversions. This CAN be accomplished in Java as well without losing type-safety and the good stuff statically-typed languages provide WITHOUT the nasty side-effects of some of the other languages that do evil things with dynamic casting. A Perl example that does some questionable math:
print ++($foo = '99'); # prints '100'
print ++($foo = 'a0'); # prints 'a1'
In Java, this is better accomplished (IMHO) by using a method I call "cross-casting".
With cross-casting, reflection is used in a lazy-loaded cache of constructors and methods that are dynamically discovered via the following static method:
Object fromString (String value, Class targetClass)
Unfortunately, no built-in Java methods such as Class.cast() will do this for String to BigDecimal or String to Integer or any other conversion where there is no supporting class hierarchy. For my part, the point is to provide a fully dynamic way to achieve this - for which I don't think the prior reference is the right approach - having to code every conversion. Simply put, the implementation is just to cast-from-string if it is legal/possible.
So the solution is simple reflection looking for public Members of either:
STRING_CLASS_ARRAY = (new Class[] {String.class});
a) Member member = targetClass.getMethod(method.getName(),STRING_CLASS_ARRAY);
b) Member member = targetClass.getConstructor(STRING_CLASS_ARRAY);
You will find that all of the primitives (Integer, Long, etc) and all of the basics (BigInteger, BigDecimal, etc) and even java.regex.Pattern are all covered via this approach. I have used this with significant success on production projects where there are a huge amount of arbitrary String value inputs where some more strict checking was needed. In this approach, if there is no method or when the method is invoked an exception is thrown (because it is an illegal value such as a non-numeric input to a BigDecimal or illegal RegEx for a Pattern), that provides the checking specific to the target class inherent logic.
There are some downsides to this:
1) You need to understand reflection well (this is a little complicated and not for novices).
2) Some of the Java classes and indeed 3rd-party libraries are (surprise) not coded properly. That is, there are methods that take a single string argument as input and return an instance of the target class but it isn't what you think... Consider the Integer class:
static Integer getInteger(String nm)
Determines the integer value of the system property with the specified name.
The above method really has nothing to do with Integers as objects wrapping primitives ints.
Reflection will find this as a possible candidate for creating an Integer from a String incorrectly versus the decode, valueof and constructor Members - which are all suitable for most arbitrary String conversions where you really don't have control over your input data but just want to know if it is possible an Integer.
To remedy the above, looking for methods that throw Exceptions is a good start because invalid input values that create instances of such objects should throw an Exception. Unfortunately, implementations vary as to whether the Exceptions are declared as checked or not. Integer.valueOf(String) throws a checked NumberFormatException for example, but Pattern.compile() exceptions are not found during reflection lookups. Again, not a failing of this dynamic "cross-casting" approach I think so much as a very non-standard implementation for exception declarations in object creation methods.
If anyone would like more details on how the above was implemented, let me know but I think this solution is much more flexible/extensible and with less code without losing the good parts of type-safety. Of course it is always best to "know thy data" but as many of us find, we are sometimes only recipients of unmanaged content and have to do the best we can to use it properly.
Cheers.
So, this is an old post, however I think I can contribute something to it.
You can always do something like this:
package com.dyna.test;
import java.io.File;
import java.lang.reflect.Constructor;
public class DynamicClass{
#SuppressWarnings("unchecked")
public Object castDynamicClass(String className, String value){
Class<?> dynamicClass;
try
{
//We get the actual .class object associated with the specified name
dynamicClass = Class.forName(className);
/* We get the constructor that received only
a String as a parameter, since the value to be used is a String, but we could
easily change this to be "dynamic" as well, getting the Constructor signature from
the same datasource we get the values from */
Constructor<?> cons =
(Constructor<?>) dynamicClass.getConstructor(new Class<?>[]{String.class});
/*We generate our object, without knowing until runtime
what type it will be, and we place it in an Object as
any Java object extends the Object class) */
Object object = (Object) cons.newInstance(new Object[]{value});
return object;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args)
{
DynamicClass dynaClass = new DynamicClass();
/*
We specify the type of class that should be used to represent
the value "3.0", in this case a Double. Both these parameters
you can get from a file, or a network stream for example. */
System.out.println(dynaClass.castDynamicClass("java.lang.Double", "3.0"));
/*
We specify a different value and type, and it will work as
expected, printing 3.0 in the above case and the test path in the one below, as the Double.toString() and
File.toString() would do. */
System.out.println(dynaClass.castDynamicClass("java.io.File", "C:\\testpath"));
}
Of course, this is not really dynamic casting, as in other languages (Python for example), because java is a statically typed lang. However, this can solve some fringe cases where you actually need to load some data in different ways, depending on some identifier. Also, the part where you get a constructor with a String parameter could be probably made more flexible, by having that parameter passed from the same data source. I.e. from a file, you get the constructor signature you want to use, and the list of values to be used, that way you pair up, say, the first parameter is a String, with the first object, casting it as a String, next object is an Integer, etc, but somehwere along the execution of your program, you get now a File object first, then a Double, etc.
In this way, you can account for those cases, and make a somewhat "dynamic" casting on-the-fly.
Hope this helps anyone as this keeps turning up in Google searches.
Try this for Dynamic Casting. It will work!!!
String something = "1234";
String theType = "java.lang.Integer";
Class<?> theClass = Class.forName(theType);
Constructor<?> cons = theClass.getConstructor(String.class);
Object ob = cons.newInstance(something);
System.out.println(ob.equals(1234));
I recently felt like I had to do this too, but then found another way which possibly makes my code look neater, and uses better OOP.
I have many sibling classes that each implement a certain method doSomething(). In order to access that method, I would have to have an instance of that class first, but I created a superclass for all my sibling classes and now I can access the method from the superclass.
Below I show two ways alternative ways to "dynamic casting".
// Method 1.
mFragment = getFragmentManager().findFragmentByTag(MyHelper.getName(mUnitNum));
switch (mUnitNum) {
case 0:
((MyFragment0) mFragment).sortNames(sortOptionNum);
break;
case 1:
((MyFragment1) mFragment).sortNames(sortOptionNum);
break;
case 2:
((MyFragment2) mFragment).sortNames(sortOptionNum);
break;
}
and my currently used method,
// Method 2.
mSuperFragment = (MySuperFragment) getFragmentManager().findFragmentByTag(MyHelper.getName(mUnitNum));
mSuperFragment.sortNames(sortOptionNum);
Just thought I would post something that I found quite useful and could be possible for someone who experiences similar needs.
The following method was a method I wrote for my JavaFX application to avoid having to cast and also avoid writing if object x instance of object b statements every time the controller was returned.
public <U> Optional<U> getController(Class<U> castKlazz){
try {
return Optional.of(fxmlLoader.<U>getController());
}catch (Exception e){
e.printStackTrace();
}
return Optional.empty();
}
The method declaration for obtaining the controller was
public <T> T getController()
By using type U passed into my method via the class object, it could be forwarded to the method get controller to tell it what type of object to return. An optional object is returned in case the wrong class is supplied and an exception occurs in which case an empty optional will be returned which we can check for.
This is what the final call to the method looked like (if present of the optional object returned takes a Consumer
getController(LoadController.class).ifPresent(controller->controller.onNotifyComplete());