If I write this line in Java:
JOptionPane.showInputDialog(null, "Write something");
Which method will be called?
showInputDialog(Component parent, Object message)
showInputDialog(Object message, Object initialSelectionValue)
I can test it. But in other cases similar to this, I want to know what happens.
The most specific method will be called - in this case
showInputDialog(Component parent, Object message)
This generally comes under the "Determine Method Signature" step of overload resolution in the spec (15.12.2), and in particular "Choosing the Most Specific Method".
Without getting into the details (which you can read just as well in the spec as here), the introduction gives a good summary:
If more than one member method is both
accessible and applicable to a method
invocation, it is necessary to choose
one to provide the descriptor for the
run-time method dispatch. The Java
programming language uses the rule
that the most specific method is
chosen.
The informal intuition is that one
method is more specific than another
if any invocation handled by the first
method could be passed on to the other
one without a compile-time type error.
In your particular case the more specific method will be called. In general, though, there are some cases where the method signature can be ambiguous. Consider the following:
public class Main {
public static void main(String[] args) {
Main m = new Main();
m.testNullArgument(null);
}
private void testNullArgument( Object o )
{
System.out.println("An Object was passed...");
}
private void testNullArgument( Integer i )
{
System.out.println("An Integer was passed...");
}
private void testNullArgument( String s )
{
System.out.println("A String was passed...");
}
}
In this case, the compiler can't decide between the method that takes an Integer and the method that takes a String. When I try to compile that, I get
reference to testNullArgument is ambiguous, both method testNullArgument(java.lang.Integer) in testnullargument.Main and method testNullArgument(java.lang.String) in testnullargument.Main match
Neither. You'll get a compiler error asking you to clarify what method you want to call. You can do so by explicitly casting the first argument:
showInputDialog((Object) null, "Write something");
or
showInputDialog((Component) null, "Write something");
Update I should have known - never doubt Jon Skeet. The problem I've referred to above only occurs when it's impossible to determine which method is more specific. Here's a test case:
public class Test {
public void doSomething(String arg1, Object arg2) {
System.out.println("String, Object");
}
public void doSomething(Object arg1, String arg2) {
System.out.println("Object, String");
}
public static void main(String[] args) {
Test test = new Test();
test.doSomething(null, null);
}
}
The above will give a compiler error.
Related
I'm trying to get into exception handling via custom exceptions.
I'm creating the class CustomExceptions and extending Exception as follows:
public class CustomExceptions extends Exception{
public CustomExceptions (String s) {
super(s);
}
However, rather than having to create multiple files for every custom exception I want, or bloating my main class file, I'd like to put all of my custom exceptions in this class and invoke them via a method
So let's say that I want to handle 2 situations: When the user tries to input a seat reservation, but the seat is already taken, and when the user tries to provide a ticket for someone outside of the age range.
Can I create 2 methods inside of the CustomExceptions class which invoke the constructor passing a custom message to it?
public void seatTaken(String s) {
String s = "The seat is taken, please choose a new one";
CustomExceptions(s);
}
public void notOldEnough(String s) {
String s = "User is not old enough for this movie.";
CustomExceptions(s)
}
}
Would this work? Or am I forced to create multiple custom exception files?
Generally custom exceptions should be defined in the top level. Because, almost universally, these exceptions are part of the interface of the package or module.
If the user cannot see them, then how are they going to catch them separately? And if you don't want to catch them separately, then why would you need separate classes?
However, if you must, you can include them into a class for which they are required:
public class SeatReservationSystem {
public static class ReservationFailedException {
... constructors taking a message ...
}
public static class SeatTakenException extends ReservationFailedException {
... constructors taking a message ...
}
public static class OutsideAgeException extends ReservationFailedException {
... constructors taking a message ...
}
....
}
After that you can create any method that returns them as required. Don't create methods that throw them as the compiler won't see those as exit points of the block you're in, and you'll get strange situations.
Here is some code to show what I mean:
// wrong
public static void throwRuntimeException() throws RuntimeException {
throw new RuntimeException();
}
// correct, but dangerous
public static RuntimeException createRuntimeException() {
return new RuntimeException();
}
public static void main(String[] args) {
String initializeMeOrThrowException;
if (new Random().nextBoolean()) {
// compiler doesn't recognize that the method always throws an exception
throwRuntimeException();
// this the compiler can understand, there is an explicit throw here:
// throw createRuntimeException();
// but this is the pitfall, it doesn't do anything:
// createRuntimeException();
} else {
initializeMeOrThrowException = "Initialized!";
}
// Compiler error for throwRuntimeException and createRuntimeException without throws:
// "The local variable initializeMeOrThrowException may not have been initialized"
System.out.println(initializeMeOrThrowException);
}
However, experience learns me that I forget the throws statement for the throw createException(...); method, and the stupid compiler doesn't warn me about that (even though the statement is utterly useless without it). So I try and not use either.
Note that I'm not certain if you should use exceptions for this. If your system is a reservation system, then refusing tickets is not that exceptional. Returning a ReservationResult makes more sense.
I can't call method serve() below.
public class GenericService {
public static class Service<T> {
public void serve(T t) {
System.out.println(t.toString());
}
}
public static Service<?> service = new Service<String>();
public static void main(String[] args) {
service.serve("Hello World!"); // 'serve(capture<?>)' cannot be applied to '(java.lang.String)'
}
}
How to call this method by force?
Why does Java dislike such calls?
UPDATE
The problem is not ClassCastException as was proposed, because in that case I would be able to write
try {
service.serve("Hello World!"); // 'serve(capture<?>)' cannot be applied to '(java.lang.String)'
}
catch (ClassCastException e) {
System.err.println("You see!? This is why I was disliking your code!");
}
but I can't.
Why?
UPDATE 2
Now, when everybody said out, a new version:
public static Service<? extends String> service = new Service<String>();
public static void main(String[] args) {
service.serve("Hello World!"); // 'serve(capture<?>)' cannot be applied to '(java.lang.String)'
((Service<String>)service).serve("Hello World!"); // Unchecked cast: 'GenericService.Service<capture<? extends String>>' to 'GenericService.Service<String>'
}
what problem is here (don't regard that String is final)?
You misunderstand what the wildcard means (this is actually a common misunderstanding about generics wildcards in Java).
Service<?> does not mean: a Service that can accept any type.
It does mean: a Service of a specific, but unknown type.
You cannot call serve, passing it a String, because the type that the ? stands for is unknown - the compiler cannot check, just by looking at the type of the variable service, if the actual service that it refers to is a Service<String>, a Service<Integer> or a Service<Whatever>, so it can't know if it should be allowed to pass a String to the serve method.
To keep it type-safe, the compiler has no other option than to not allow you to call the method.
How to call this method by force?
You can force it by casting:
((Service<String>) service).serve("Hello World!");
(But keep in mind that casting means you are giving up on type-safety, in general you should avoid casting as much as possible).
Wildcards in generics has not for aim to allow the usage of any type. It is a way to identify an unknown and invariable type.
In your code, ? is of type String but the compiler can't guess it. You could change it later with a Service<Integer> and have ClassCastException at runtime by forcing String objects in it.
There is no way to cast an object to a captured type (= wildcard).
If you want to accept every object that declare the toString() method then you should use Service<Object> instead of Service<?>:
public static Service<Object> service = new Service<Object>();
I'm trying to write an expression or series of statements of Java source code that when written inside a static method evaluates to null, but if the method is non-static evaluates to this.
My initial idea was to 'overload' on static vs non-static, as below:
public class test {
public void method1() {
System.out.println(getThisOrNull());
}
public static void method2() {
System.out.println(getThisOrNull());
}
private static Object getThisOrNull() {
return null;
}
private Object getThisOrNull() {
return this;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
Unfortunately this isn't actually legal Java, you can't 'overload' like that and it just gives a compiler error:
test.java:14: error: method getThisOrNull() is already defined in class test
private Object getThisOrNull() {
^
1 error
Clearly in an ideal world I wouldn't write it like that to begin with, but the problem is this code will be generated automatically by a tool that is not really semantically or syntactically enough to distinguish between the static vs non-static case.
So, how can I write some source code that, although byte for byte identical compiles and behaves differently in depending on the presence of the static modifier for the method?
This can be achieved with a trick and a bit of help from Java's reflection facilities. It's ugly, but it works:
import java.lang.reflect.Field;
public class test {
public void method1() {
System.out.println(getThisOrNull(new Object(){}));
}
public static void method2() {
System.out.println(getThisOrNull(new Object(){}));
}
private static Object getThisOrNull(final Object o) {
for (Field f: o.getClass().getDeclaredFields()) {
if (f.getType().equals(test.class)) {
try {
return f.get(o);
}
catch (IllegalAccessException e) {
// Omm nom nom...
}
}
}
return null;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
This compiles and runs as hoped for:
test#183f74d
test#183f74d
null
The trick that makes this possible is the use of new Object(){}, which creates a new, anonymous class within the existing method that we're trying to figure out if it's static or not. The behaviour of this is subtly different between the two cases.
If the goal were just to figure out if the method is static or not we could write:
java.lang.reflect.Modifiers.isStatic(new Object(){}.getClass().getEnclosingMethod().getModifiers())
Since we want to get this (when available) we need to do something slightly different. Fortunately for us classes defined within the context of an instance of an object in Java get an implicit reference to the class that contains them. (Normally you'd access it with test.this syntax). We needed a way to access test.this if it existed, except we can't actually write test.this anywhere because it too would be syntactically invalid in the static case. It does however exist within the object, as a private member variable. This means that we can find it with reflection, which is what the getThisOrNull static method does with the local anonymous type.
The downside is that we create an anonymous class in every method we use this trick and it probably adds overheads, but if you're backed into a corner and looking for a way of doing this it does at least work.
Is there a method/function in Java that checks if another method/function is available just like function_exists(functionName) in PHP?
Here I am referring to a method/function of static class.
You can find out if a method exists in Java using reflection.
Get the Class object of the class you're interested in and call getMethod() with the method name and parameter types on it.
If the method doesn't exist, it will throw a NoSuchMethodException.
Also, please note that "functions" are called methods in Java.
Last but not least: keep in mind that if you think you need this, then chances are that you've got a design problem at hand. Reflection (which is what the methods to inspect the actual Java classes is called) is a rather specialized feature of Java and should not generally be used in business code (although it's used quite heavily and to some nice effects in some common libraries).
I suspect you're looking for Class.getDeclaredMethods and Class.getMethods which will give you the methods of a class. You can then test whether the one you're looking for exists or not, and what it's parameters are etc.
You can use Reflections to lookup if the method exists:
public class Test {
public static void main(String[] args) throws NoSuchMethodException {
Class clazz = Test.class;
for (Method method : clazz.getDeclaredMethods()) {
if (method.getName().equals("fooBar")) {
System.out.println("Method fooBar exists.");
}
}
if (clazz.getDeclaredMethod("fooBar", null) != null) {
System.out.println("Method fooBar exists.");
}
}
private static void fooBar() {
}
}
But Reflection is not really fast so be careful when to use it (probably cache it).
Try using the Class.getMethod() method of the Class class =)
public class Foo {
public static String foo(Integer x) {
// ...
}
public static void main(String args[]) throws Exception {
Method fooMethod = Foo.class.getMethod("foo", Integer.class);
System.out.println(fooMethod);
}
}
Here my solution using reflection...
public static boolean methodExists(Class clazz, String methodName) {
boolean result = false;
for (Method method : clazz.getDeclaredMethods()) {
if (method.getName().equals(methodName)) {
result = true;
break;
}
}
return result;
}
You can use the reflection API to achieve this.
YourStaticClass.getClass().getMethods();
You can do this like this
Obj.getClass().getDeclaredMethod(MethodName, parameterTypes)
A while ago I had a similar question when using Class.getMethod and autoboxing, and it made sense to implement this in your own lookup algorithm. But what really confused me a little was that the following is not working either:
public class TestClass
{
public String doSomething(Serializable s)
{
return s.toString();
}
public static void main(String[] args) throws SecurityException, NoSuchMethodException
{
TestClass tc = new TestClass();
Method m = tc.getClass().getMethod("doSomething", String.class);
}
}
String.class implements the Serializable interface and I really expected it to be included in the lookup method. Do I have to consider this in my own lookup algorithms as well?
EDIT: I did read the Javadoc, so let me emphasise the second part of the question: And if so do you have suggestions on how to do that fast (I already had to add some custom matching and converting algorithms and I don't want it to get too slow)?
As per your edit, you can make use of Class#isAssignableFrom(). Here's a basic kickoff example (leaving obvious (runtime) exception handling aside):
package com.stackoverflow.q2169497;
import java.io.Serializable;
import java.lang.reflect.Method;
public class Test {
public String doSomething(Serializable serializable) {
return serializable.toString();
}
public static void main(String[] args) throws Exception {
Test test = new Test();
for (Method method : test.getClass().getMethods()) {
if ("doSomething".equals(method.getName())) {
if (method.getParameterTypes()[0].isAssignableFrom(String.class)) {
System.out.println(method.invoke(test, "foo"));
}
}
}
}
}
This should print foo to stdout.
The javadoc for Class.getMethod is very explicit:
The parameterTypes parameter is an
array of Class objects that identify
the method's formal parameter types,
in declared order.
It offers no scope for subtypes.
getMethod isn't meant to find methods which are compatible with the given parameter types - it's meant to find methods with exactly the given parameter types.
You'd need to call getMethods() to find all the methods, then filter by name and number of parameters, then work out which of those are actually applicable.
Why would you call getMethod with String.class? Method signatures are exactly mapped. It doesn't make any sense to look up a method by the same criteria as if you will call them.