Removing compiler's warning from a method call, advise needed - java

As part of my Utils class, i have both
public static boolean isStringEmptyOrNull(String... s) {
When testing for a null condition
assertTrue(Utils.isStringEmptyOrNull(null));
I get "The argument of type null should explicitly be cast to String[] for the invocation of the varargs method isStringEmptyOrNull(String...) from type Utils. It could alternatively be cast to String for a varargs invocation" warning.
I'd rather not case anything though. This test is designed to simulate a condition where argument passed to the method is a null.
Is there a way to remove this warning without changing the signature of the method?

You should probably test both of these cases:
assertTrue(Utils.isStringEmptyOrNull(new String[] { null }));
assertTrue(Utils.isStringEmptyOrNull((String[]) null));
... although it's not clear to me why a method which sounds like it should only take a single string is taking an array of strings in the first place, to be honest.
(Is it obvious to you which of those invocations you meant without the cast? It isn't obvious to me... I'd have to look it up to check.)

If you are trying to mimic the way a client of your library function would call your code, you should take advantage of the fact that they will not call this particular method with the literal "null" (what would be the point?)
Instead, they would pass in some variable or expression. Since that's the case, you can do something like this and avoid casting:
String nullString = null;
assertTrue(Utils.isStringEmptyOrNull(nullString));

You could specifically tell the compiler to ignore the warning using #SuppressWarnings("all").

Well that warning's there for a reason: when you call your method with null argument, since null is all and any type in Java (including Array), the compiler effectively will not know if you're calling the var-args method with an array or a non-array object (each of which is treated differentlly when var-args arguments are used). What you can do is annotate the method with SuppressWarnings("All") and then test for null before doing anything with the argument(s)

Change your test like so:
String nullString = null;
assertTrue(Utils.isStringEmptyOrNull(nullString));
Rather curious why you use a vararg method for this in the first place though...

Related

How to pass parameter in Supplier function with method reference operator(::)

Sorry, it seems to be very basic in functional programming but I am not getting this idea. Actually I have a method in my code which consumes a method and another param as a parameter.
private <R> CompletableFuture<R> retryRequest(Supplier<CompletableFuture<R>> supplier, int maxRetries)
I want to call this function and pass another method(anOtherMethod) which taking one integer parameter:
CompletableFuture<Boolean> retry = this.retryRequest(this:: anOtherMethod, 2);
Not getting this how I can call this retryRequest and give anOtherMethod(123)?
I know it can work like this:
CompletableFuture<Boolean> retry = this.retryRequest(()-> anOtherMethod(123), 2);
You cannot instantiate a lambda with a specific captured value like 123 in the pure method reference variant.. You need to write the explicit lambda version with arrow, if you want to pass captured values other than the instance to execute the method on. Read more on capturing values in lambdas in this answer: Enhanced 'for' loop and lambda expressions
The only exception is an object, which itself becomes the first parameter.
Assume a signature that expects a Consumer of a String:
public void something(Consumer<String> job) {
...
The above signature will enable you to write the following calls:
String myString = " Hey Jack ";
something(myString::trim);
something(s -> s.trim());
Both do the same, and this is maybe unintuitive, because one takes an argument (the instance reference myString) and one seem not to (but it actually does, too). This works, because the compiler tries two possible resolutions for a lambda method reference (the above version with ::). On one hand, the compiler can apply signatures, as if the called method did not have any parameters, and none need passing. This is the case for myString.trim. But the compiler will also check, whether there is a static method String.trim(myString) (which luckiely there is not). If you wanted to call a static method without any parameters, then you'd have to call the class identifier with the function reference like so:
something(String::trim); // this version of trim does not exist.
This is sometimes even a problem, because if a class offers a static version of a method and an instance-related one, you get ambiguity:
public void somethingElse(Function<Integer, String> transformation) {...}
// This will not compile:
somethingElse(Integer::toString);
The above example will not compile, because the toString method exists twice, once as static Integer.toString(someInt) and once as instance related someInteger.toString().

In Java, what is the difference between using the toString method vs explicit String casting vs plus quotes (ex. myObj+"")?

What is the difference between plus quotes (+"") and using a "toString()" method or even explicitly casting with something like (String) myObject? Trade-offs?
myObject.toString()
vs.
myObject+""
or even vs.
(String) myObject
More specifically, is there any time using the myObj+"" method can get you into trouble?
Edited for clarity
EDIT 2:
Seems String.valueOf(myObj); is the prefered method for avoiding a null pointer. That said: Is there ever a time when the following is false?
String.valueOf(myObj).equals(myObj+"")
As of Java 7, if you want to avoid a NullPointerException, you can simply use one of these:
Objects.toString( myObject )
Objects.toString( myObject, "defaultValueWhenMyObjectIsNull" )
In all versions of Java, the first of these can also be accomplished with the following, as noted by #NobuGames in the first comment below:
String.valueOf( myObject )
The mechanisms you cite each has a flaw.
myObject.toString() // throws NullPointerException if myObject is null.
myObject+"" // Hack; impairs understandability.
(String) myObject // throws ClassCastException unless myObject is a String or null
EDIT (after question edit)
is there any time using the myObj+"" method can get you into trouble?
Yes, you can confuse other programmers. The intent of the hack is not clear. This can lead to increased cost in time, and increased risk of someone "fixing" it.
However, in terms of just the compiler, you're fine. From the Java Language Specification, section 15.18: String concatentation operator +:
If only one operand expression is of type String, then string conversion (ยง5.1.11) is performed on the other operand to produce a string at run time.
And from that cited section 5.1.11: String conversion:
If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l).
Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null, then the string "null" is used instead.
This second case leads to a difference that you asked about.
Is there ever a time when the following is false? String.valueOf(myObj).equals(myObj+"")
No, but there's a time when that throws a NullPointerException. When myObj is a non-null reference to an object whose toString() method returns null, then String.valueOf(myObj) will be null. Calling the equals method will throw the NullPointerException.
But I suspect you're asking whether there's ever a time the two have different values. Yes, they can have different values. Objects.toString() and String.valueOf() can return null values. The hack will always have a non-null value.
That said, returning null from toString() is somewhat bad form. The JLS acknowledges that it can happen, but the API implies that it should not. Personally, if I were concerned about this case, I would handle it in some way other than the hack.
This code:
myObject+""
Is translated by the compiler to this:
new StringBuilder().append(myObject).append("").toString()
The StringBuilder append method does a null check on the input argument, appending the text "null".
The String class has an overloaded valueOf method, so you can also do:
String.valueOf(myObject)
Which will do a null check, returning the text "null".
Casting to String is going to be highly contextual, so more than one technique may apply here. If you are expecting to directly cast to String, my advice would be to prepare for it. If there is a chance it can be null, then check for it. Or make the API promise not to hand you a null. That is, this is a separation of concerns and a layering of responsibilities.
However, IMO, any sufficiently complicated class ought to have a toString() method. It can be for debugging, or used as a property for computation, but it ought to be human readable. There are few cases where a human-readable version of the object is not warranted, in my experience.
Relying on overloading the + operator feels like a hack, yes.

Dynamically casting to primitives in Java

Edit: This has since been solved. Thanks to everyone who helped. Invoking the method after casting the object as the correct wrapper class worked. But String.valueOf() is much, much simpler to achieve the same effect.
Hello--
What I'm trying to do may not even be possible. I've spent a few hours now researching and experimenting with various things, so I figured I'd finally ask around to see if anyone knows if this is even possible.
Is it possible, using reflection, to dynamically cast a wrapper for a primitive of an unknown type as a primitive?
I'm basically trying to create a generic toString function which can handle the conversion of any type of primitive to a string. Such a seemingly simple thing is frustratingly difficult (and I am aware I could just test each type to see if it is of type Wrapper.class and cast it specifically, but at this point I'm just pursuing this out of stubbornness).
The following throws a ClassCastException. The primClass class appears to be the right one (gives "int" when printing primClass.getName()).
private String toString(Number obj){
String result = "";
try{
Class objClass = obj.getClass();
Field field = objClass.getDeclaredField("TYPE");
Class primClass = (Class)field.get(obj);
Method method = objClass.getMethod("toString", new Class[]{primClass});
Object args = new Object[]{primClass.cast(obj)};
result = (String)method.invoke(null, args);
}catch(Exception ex){
//Unknown exception. Send to handler.
handleException(ex);
}
return result;
}
So I'm a bit at a loss, really. Anyone have any ideas? Any help would be greatly appreciated.
Perhaps I'm missing something, but obj.toString() would do.
If you look at the implementations, it is calling String.valueOf(value) which in turn calls Double.toString(..) or Long.toString(..) or whatever. So, calling toString() automatically calls the required method. Without any reflection from your part.
You might want to have a look at Apache Commons Lang, Especially ToStringBuilder.reflectionToString(). Even if you don't want to introduce a dependency just for a toString(), it's open source so you can have a look at the implementation.
method.invoke accept the Wrapper types instead of the primivtes types.
Perhaps there is something I don't understand in your question but for primitive, you can do ""+primitive to cast it to a String.
What you are trying to do doesn't really make sense.... when your function is called with a primitive argument (e.g. an int) then it will automatically get boxed into an Integer. So you might as well just call obj.toString() on it.....
However if you really want to do something special with primitives, you might want to do something like the following using method overloading:
private String toString(Object obj){
return obj.toString();
}
private String toString(int intValue) {
// code to return string for the primitive int case, assuming it is different
}
// more overloads for other primitive argument types as needed.....
This can be a very useful technique for dealing with primitives in some cases.
The immediate problem in your code is that obj is an Object, and therefore cannot be an instance of a primitive type. (It must be an instance of the corresponding wrapper type). The primClass.cast(obj) call must fail for any primitive type class.
But if you simply want to turn a primitive wrapper instance to a String, just call the instance's toString() method.
String.valueOf(arg) will do it nicely too.

Calling closest fitting method

As part of developing a small ScriptEngine, I reflectively call java methods. A call by the script engine gives me the object the method name and an array of arguments. To call the method I tried to resolve it with a call to Class.getMethod(name, argument types).
This however only works when the classes of the arguments and the classes expected by the Method are the same.
Object o1 = new Object();
Object out = System.out;
//Works as System.out.println(Object) is defined
Method ms = out.getClass().getMethod("println",o1.getClass());
Object o2 = new Integer(4);
//Does not work as System.out.println(Integer) is not defined
Method mo = out.getClass().getMethod("println",o2.getClass());
I would like to know if there is a "simple" way to get the right method, if possible with the closest fit for the argument types, or if I have to implement this myself.
Closest fit would be:
Object o1 = new Integer(1);
Object o2 = new String("");
getMethod(name, o1.getClass())//println(Object)
getMethod(name, o2.getClass())//println(String)
Update:
To clarify what I need:
The Script Engine is a small project I write in my free time so there are no strikt rules I have to follow. So I thought that selecting methods called from the Engine the same way the java compiler selects methods at compile time only with the dynamic type and not the static type of the Object would work.(with or without autoboxing)
This is what I first hoped that the Class.getMethod() would solve. But the Class.getMethod() requires the exact same Classes as argument types as the Method declares, using a subclass will result in a no such method Exception. This may happen for good reasons, but makes the method useless for me, as I don't know in advance which argument types would fit.
An alternate would be to call Class.getMethods() and iterate through the returned array and try to find a fitting method. This would however be complicated if I don't just want to take the first "good" method which I come across, so I hoped that there would be an existing solution which at least handles:
closest fit: If arg.getClass() ==
subclass and methods m(Superclass),
m(Subclass) then call m(Subclass)
variable arguments:
System.out.printf(String ,String...)
Support for autoboxing would be nice, too.
If a call cannot be resolved it may throw an exception ( ma(String,Object), ma(Object, String), args= String,String)
(If you made it till here, thanks for taking the time to read it:-))
As others have pointed out there is no standard method that does this, so you are going to have to implement your own overload resolution algorithm.
It would probably make sense to follow javac's overload resolution rules as closely as possible:
http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#292575
You can probably ignore generics for a dynamically-typed scripting language, but you might still benefit from the bridge methods that the compiler generates automatically.
Some pitfalls to watch out for:
Class.isAssignableFrom does not know about automatic widening primitive conversions, because these are syntactic sugar implemented in the compiler; They do not occur in the VM or class hierarchy. e.g. int.class.isAssignableFrom(short.class) returns false.
Similarly Class.isAssignableFrom does not know about auto-boxing. Integer.class.isAssignableFrom(int.class) returns false.
Class.isInstance and Class.cast take an Object as an argument; You cannot pass primitive values to them. They also return an Object, so they cannot be used for unboxing ((int) new Integer(42) is legal in Java source but int.class.cast(new Integer(42)) throws an exception.)
I would suggest that you use getMethods(). It returns an array of all public methods (Method[]).
The most important thing here is:
"If the class declares multiple public member methods with the same parameter types, they are all included in the returned array."
What you will then need to do is to use the results in this array to determine which one of them (if any) are the closest match. Since what the closest match should be depends very much on your requirements and specific application, it does make sense to code it yourself.
Sample code illustrating one approach of how you might go about doing this:
public Method getMethod(String methodName, Class<?> clasz)
{
try
{
Method[] methods = clasz.getMethods();
for (Method method : methods)
{
if (methodName.equals(method.getName()))
{
Class<?>[] params = method.getParameterTypes();
if (params.length == 1)
{
Class<?> param = params[0];
if ((param == int.class) || (param == float.class) || (param == float.class))
{
//method.invoke(object, value);
return method;
}
else if (param.isAssignableFrom(Number.class))
{
return method;
}
//else if (...)
//{
// ...
//}
}
}
}
}
catch (Exception e)
{
//some handling
}
return null;
}
In this example, the getMethod(String, Class<?>) method will return a method that with only one parameter which is an int, float, double, or a superclass of Number.
This is a rudimentary implementation - It returns the first method that fits the bill. You would need to extend it to create a list of all methods that match, and then sort them according to some sort of criteria, and return the best matching method.
You can then take it even further by creating the more general getMethod(String, Class<?>) method, to handle more of the possible "close match" scenarios, and possibly even more than one paramter
HTH
Edit: As #finnw has pointed out, be careful when using Class#isAssignableFrom(Class<?> cls), due to its limitations, as I have in my sample code, testing the primitives separately from the Number objects.
AFAIK, there is no simple way to do this kind of thing. Certainly, there's nothing in the standard Java class libraries to do this.
The problem is that there is no single "right" answer. You need to consider all of your use-cases, decide what the "right method" should be and implement your reflection code accordingly.

Why is this generic method unsafe?

The following method generates a warning, but it looks safe to me. I'm sure the problem is with me:
public <S extends CharSequence> S foo(S s) {
return (S) new StringBuilder(s);
}
It looks like this will always return the argument s. Can anyone show an example that would cause this method to throw an exception?
Edit: I'm not particularly interested in the question of whether generics are necessary here. Rather, I'm looking for a demonstration of how this method is unsafe.
It's unsafe because while StringBuilder is a CharSequence, it isn't necessarily of type S (in fact, it almost certainly won't be). You can see this failing just by passing a String into your method. This will construct a StringBuilder using your String as an argument, and then try to cast your StringBuilder to String (which will fail).
There's probably no need to use generics here at all, this should work fine:
public CharSequence foo(CharSequence s) {
return new StringBuilder(s);
}
For example this will compile:
String a = foo("ss");
but it will fail at runtime:
ClassCastException: java.lang.StringBuilder cannot be cast to java.lang.String
since foo returns S, the type of your input parameter (String in this case).
I think that you don't need to use generics here (as skaffman said in his answer):
public StringBuilder foo(CharSequence s) {
return new StringBuilder(s);
}
foo("test");
is enough to make java try to cast a StringBuilder in a String.
Your code is guaranteed o be wrong, can you explain what you're trying to achieve plase ?
The unsafety here lies not within the method itself (though it has its problems, too) but at the call site. The use of S for the input argument's type as well as for the return value tells the compiler, that whatever the type of object may be that is passed to the function, the result has the same type (or a derived type, actually).
Thus, the compiler is allowed to assume, that in the call
foo("hello, world")
the result will be a java.lang.String, while in the call
foo(new StringBuffer("hello, world"))
the result will be a StringBuffer, and so on. In both cases, however, your method does not return what it was supposed to return, namely, an object of the same type as the input argument. Instead, a StringBuilder is returned.
Actually, the only kind of input argument your method will work with is a StringBuilder, anything else will be doomed to crash with a ClassCastException sooner or later, as the compiler might (and often does) insert (hidden) casts at the call sites.
And of course, as others have already pointed out, the use of generics is not really necessary here, anyway.
The return type of your method code is ALWAYS a StringBuilder.
That is because the declared type of the expression 'new StringBuilder(x)' is ALWAYS a StringBuilder, whatever the X.
It is TOTALLY pointless to try and cast this to anything. The "S" information is part of the erasure, which exists only at compile-time and is erased by the time the program runs, that is, run-time. (Casting is a run-time thing exclusively, and casting something to some type/class whose identity has been erased a run-time, is indeed totally pointless.)
my Java is rusty, but would this method not throw whatever exceptions
new StringBuilder(s)
can throw?

Categories

Resources