Java - Method picking algorithm [duplicate] - java

This question already has answers here:
Using null in overloaded methods in Java [duplicate]
(3 answers)
Closed 7 years ago.
I was messing around with methods and was looking, which Method will be executed if I make two Methods named "hello", with different objects they want and pass a "null" to the method:
public static void main(String... args) {
hello(null);
}
public static void hello(Window w) {
System.out.println("Hello");
}
public static void hello(Frame f) {
System.out.println("Bye");
}
The output was every time "Bye", but I still don't understand the logic behind that.
After a short research with google, without of any explanation, I decided to ask the question here.
I hope that someone can explain the selection algorithm or give me a link to a explanation.

The compiler prefers the most specialized type:
public class Parent {
public static void main(String... args) {
hello(null); // takes `Child`
}
public static void hello(Parent _) {
System.out.println("SuperClass");
}
public static void hello(Child _) {
System.out.println("SubClass");
}
}
class Child extends Parent {
}
For the reason, take a look at this thread, #Hayden already mentioned in his comment.

Java will choose the most specific of the two methods provided (See the Java Language Specification)
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.
As the class hierarchy for Frame is
java.lang.Object
java.awt.Component
java.awt.Container
java.awt.Window
java.awt.Frame
An the class hierarchy for Window is
java.lang.Object
java.awt.Component
java.awt.Container
java.awt.Window
Frame is the most specific method, and then, your public static void hello(Frame f) will be chosen.

Related

Method overloading including parent and child class [duplicate]

This question already has answers here:
How is ambiguity in selecting from overloaded methods resolved in Java?
(5 answers)
Closed 4 years ago.
Why does the following code print "string"? Why is there no error because the method call is ambiguous?
class Mixer {
void print(String s) {
System.out.println("string");
}
void print(Object o) {
System.out.println("object");
}
public static void main(String[] args) {
Mixer m = new Mixer();
m.print(null);
}
}
Explanation
The String-method is chosen because it is the most specific of those types.
Since both methods would be accessible and applicable Java selects the most specific of both, this is described in the Java Language Specification in detail.
See JLS§15.12.2 which says:
There may be more than one such method, in which case the most specific one is chosen. The descriptor (signature plus return type) of the most specific method is one used at run time to perform the method dispatch.
JLS§15.12.2.5 lists all rules that are used to determine the most specific method.
Example
Take a look at the following methods:
public void foo(Object o) { ... }
public void foo(AbstractCollection<String> o) { ... }
public void foo(AbstractList<String> o) { ... }
public void foo(ArrayList<String> o) { ... }
With each method the specified type gets more specific, if you give an ArrayList or null it will thus first use the lowest method.

Directly access methods from another Class

I want to be able to use a method from another class directly.
import package.dialog;
public class Class1 {
public static void main(String[] args) {
dialog.dialog("This is a dialog");
}
}
import javax.swing.JOptionPane
public class dialog {
public static void dialog(String message) {
JOptionPane.showMessageDialog(null, message);
}
}
This code works excactly as it's supposed to, but as you can see I'm using dialog.dialog(). I was wondering wether there is a way to use just use dialog() directly?
No, this isn't possible. Consider the following situation:
import package.dialog;
public class Class1 {
public static void main(String[] args) {
// Omit the class and call the dialog method "directly"
dialog("This is a dialog");
}
}
import javax.swing.JOptionPane
public class dialog {
public static void dialog(String message) {
JOptionPane.showMessageDialog(null, message);
}
}
public class SomeOtherClass {
public static void dialog(String message) {
// Perform some action
}
}
How would the compiler know which one you intended to call - the dialog method in the dialog class, or the dialog method in SomeOtherClass?
Programming languages are generally very carefully designed to avoid permitting this kind of ambiguity.
One notorious example of poor design (and the potential difficulty with doing what you suggest) is the diamond problem in C++ and other languages with multiple inheritance, which is an ambiguity that results from something very similar to what you're proposing. In fact, that's one of the major reasons that C# and Java banned multiple inheritance. Point being that this is really not something you'd like languages to have.
Ultimately, that would make code more difficult to read and potentially ambiguous just to save a little typing. Remember that, for readability, it's always better to be as explicit as possible about your intent.
Firstly, your example doesn't compile because you cannot name your package "package". "package" is a Java keyword and not allowed to use as an identifier.
So we call it "mypackage". And according to Java conventions you should name classes with first letter uppercase. So I will use Dialog instead of dialog for the class name in my example below.
Then you can use a static import to call the method dialog() without prefix.
import static mypackage.Dialog.*;
public class Class1 {
public static void main(String[] args) {
dialog("This is dialog");
}
}

How can instanceof return true for a class that has a private constructor?

This is a question from this book: https://www.cl.cam.ac.uk/teaching/0506/ConcSys/cs_a-2005.pdf page 28
Can you write an additional Java class which creates an
object that, when passed to the test method causes it to
print “Here!”? As I say in the code, editing the class A
itself, or using library features like reflection, serialization,
or native methods are considered cheating! I’ll provide
some hints in lectures if nobody can spot it in a week or
so. None of the PhD students has got it yet.
public class A {
// Private constructor tries to prevent A
// from being instantiated outside this
// class definition
//
// Using reflection is cheating :-)
private A() {
}
// ’test’ method checks whether the caller has
// been able to create an instance of the ’A’
// class. Can this be done even though the
// constructor is private?
public static void test(Object o) {
if (o instanceof A) {
System.out.println("Here!");
}
}
}
I know the question is a lot unclear. I can think of many different 'hack-ish' solutions but not sure if they will be counted as 'cheating' or not :)
I can't find the official answer so asking you for what would be a good answer.
If we consider that nesting class A does not "modify it" (as, technically, all lines of code are intact) then this solution is probably the only valid option:
class B
{
static
public class A {
// Private constructor tries to prevent A
// from being instantiated outside this
// class definition
//
// Using reflection is cheating :-)
private A() {
}
// ’test’ method checks whether the caller has
// been able to create an instance of the ’A’
// class. Can this be done even though the
// constructor is private?
public static void test(Object o) {
if (o instanceof A) {
System.out.println("Here!");
}
}
}
public static void main (String[] args) throws java.lang.Exception
{
A.test(new A());
}
}
What I mean is, technically it follows all the rules:
Can you write an additional Java class which creates an object that, when passed to the test method causes it to print “Here!”? - Done
As I say in the code, editing the class A itself ... considered cheating! - Technically, the class is unedited. I copy pasted it into my code.
... or using library features like reflection, serialization, or native methods are considered cheating! - Done
If, however, you decide that nesting class A should not be allowed, then I believe there is no proper solution to the problem given the current definition. Also, given the section of the book this task is given in, I bet that the author wanted to make the constructor protected but not private.
Somehow, I don't like this sort of questions. It's from a lecture back in 2005, and according to websearches, it seems that nobody has found "the" solution until now, and no solution has been published.
The constraints are clear, but the question of what is allowed or not is somewhat fuzzy. Every solution could be considered as "cheating", in one or the other way, because a class with a private constructor is not meant to be subclassed. That's a critical security mechanism, and the responsible engineers are working hard to make sure that this security mechanism cannot be trivially circumvented.
So of course, you have to cheat in order to solve this.
Nevertheless, I spent quite a while with this, and here's how I eventually cheated it:
1.) Download the Apache Bytecode Engineering Library, and place the bcel-6.0.jar in one directory.
2.) Create a file CreateB.java in the same directory, with the following contents:
import java.io.FileOutputStream;
import org.apache.bcel.Const;
import org.apache.bcel.generic.*;
public class CreateB
{
public static void main(String[] args) throws Exception
{
ClassGen cg = new ClassGen("B", "A", "B.java",
Const.ACC_PUBLIC | Const.ACC_SUPER, new String[] {});
ConstantPoolGen cp = cg.getConstantPool();
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.VOID,
Type.NO_ARGS, new String[] {}, "<init>", "B", il, cp);
il.append(InstructionFactory.createReturn(Type.VOID));
method.setMaxStack();
method.setMaxLocals();
cg.addMethod(method.getMethod());
il.dispose();
cg.getJavaClass().dump(new FileOutputStream("B.class"));
}
}
3.) Compile and execute this class:
javac -cp .;bcel-6.0.jar CreateB.java
java -cp .;bcel-6.0.jar CreateB
(note: On linux, the ; must be a :). The result will be a file B.class.
4.) Copy the class that was given in the question (verbatim - without any modification) into the same directory and compile it.
5.) Create the following class in the same directory, and compile it:
public class TestA
{
public static void main(String[] args)
{
A.test(new B());
}
}
6.) The crucial step: Call
java -Xverify:none TestA
The output will be Here!.
The key point is that the CreateB class creates a class B that extends A, but does not invoke the super constructor. (Note that an implicit super constructor invocation would normally be added by the compiler. But there's no compiler involved here. The bytecode is created manually). All this would usually fail with a VerifyError when the class is loaded, but this verification can be switched off with -Xverify:none.
So in summary:
The class A itself is not edited (and also its byte code is not edited, I hope this is clear!)
No reflection
No serialization
No custom native methods
There are a few options here:
Create a class:
public class Y extends A {
public static void main(String[] args) throws Exception {
X.test(new Y());
}
}
And then edit the bytecode and remove the call to X.. Of course this violates the JVM specification and has to be run with -Xverify:none as said above. This is essentially the same as the one #Marco13.
Option 2:
import sun.misc.Unsafe;
public class Y extends A {
public static void main(String[] args) throws Exception {
Unsafe uf = Unsafe.getUnsafe();
X.test((X) uf.allocateInstance(X.class));
}
}
Compile the code and run it by putting your classpath in the sysloader (otherwise it won't work):
$ java -Xbootclasspath/p:. Y
Both work for me :) Of course, they are both cheating. The first option isn't Java. The second is, well, evil :)
If I find out another way, I'll post it :)
In any case this can't be done without low-level tricks. The JVM Specification explicitly prohibits the creation of an object without calling the constructor as the object in the stack is uninitialized. And the JVM Specification explicitly prohibits not calling the super constructor. And the JVM Specification explicitly requires verification of access protection.
Still funny, though :)
Java can support unicode class name:)
The A in "if (o instanceof A)" could be different from the A in "public class A"
For example, the code below will print "Here!" instead of "bad".
A.java
public class A {
// Private constructor tries to prevent A
// from being instantiated outside this
// class definition
//
// Using reflection is cheating :-)
private A() {
// A: U+0041
}
// ’test’ method checks whether the caller has
// been able to create an instance of the ’A’
// class. Can this be done even though the
// constructor is private?
public static void test(Object o) {
if (o instanceof А) {
System.out.println("Here!");
}
}
}
А.java
public class А {
// A: U+0410, not A: U+0041
}
Main.java
public class Main {
public static void main(String[] args) {
A.test(new А());
}
}

How to write a Hello World application in Java? [duplicate]

This question already has answers here:
Why main() method is needed in java main class
(6 answers)
Closed 5 years ago.
I have been trying to make the Hello World Java application. But when I try to run the program it says that my selection has no main type. Here is my source code.
public class HelloWorldClass {
System.out.println("Hello world!");
}
Because it has no main() method where the code would take the starting point. Use this
public class HelloWorldClass {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
Please note there are some of the things you should always take a note of while programming. Which is also known as the syntax of the language.
Java requires you to have the class written as the FileName, HelloWorldClass is the name of the file of yours.
Then, any data type of it. In my case it is void which means it won't return anything to you in the end.
Also, you should write String[] args which is the Parameter to the method. I was last night trying to understand why I should write these? There is a method, which runs without these, but Java recommends you to add the parameters.
When running Java you need a main method so the compiler knows what to run:
public class HelloWorldClass {
public static void main(String[] args)
{
System.out.println("Hello world!");
}
}

explicitly said that class implements interface

What is the real reason that in Java, and similar languages, must be explicitly said that a class implements an interface?
Imagine implicit implementation:
interface Flyer { void fly(); }
public class Duck { public void fly() {...} }
public class Plane { public void fly() {...} }
public class Hoe { void hangAround() {...} }
void startFlying(Flyer flyer) {...}
void race() {
...
startFlying(duck); // OK
startFlying(plane); // OK
startFlying(hoe); // Compilation error.
}
Compiler knows method's signatures, return type (and modifier, of course). At this point it seems clear that there is no need to explicitly specify that Duck and Plane implements Flyer.
I would said that "implements XYZ" may be removed from Java without worries.
No difference, check at compilation time so it's OK.
In the other hand:
#JBNizet mentioned different meaning of methods with the same signature and return type.
I will use his example:
interface Runner { void run(); }
public class Guy { public void run(); }
public class Gal { public void run(); }
void startRunning(Runner r) {...}
void race() {
startRunning(guy); // OK
startRunning(gal); // OK
startRunning(runnableThread); // OK
}
OK for compiler, OK for startRunning() (OK for me). It's up to your philosophy if this is OK for you or not.
Explicit:
public class Guy **implements Runner **{ public void run(); }
public class Gal **implements Runner **{ public void run(); }
In bold (or text between ** and **) is the price which you must pay for
void race() {
startRunning(guy); // OK
startRunning(gal); // OK
startRunning(runnableThread); // Compilation error!
}
Note compilation error so you can see the issue before testing.
If it's intended to use runnableThread in startRunning() as well you must do it even more explicitly (enough time to realize what you are doing).
"I wondered how much of time is wasted by resolving issues related to typing "implements XYZ" compared to time wasted by resolving issues with implicitly implemented interfaces. If it's way more better for implicitly implemented interface then I hate Java designers for their decision and that they force us to belive it's better :-)"
Ladybug and airbus (and duck)
I think the issue with implicitly implemented interface is only theoretical and rare in real.
public class Airbus {
void takeOff() {...}
void land() {...}
Passenger[] getPassengers() {...}
}
public class Ladybug {
void takeOff() {...}
void land() {...}
}
public class Duck {
void takeOff() {...}
void land() {...}
Passenger[] getPassengers() {...}
}
public interface Aircraft {
void takeOff();
void land();
Passenger[] getPassengers();
}
public void fly(Aircraft aircraft) {
aircraft.takeOff();
for (Passenger p : aircraft.getPassengers()) {...}
aircraft.land();
}
public void airport() {
fly(airbus_a380); // OK
fly(ladybug); // Compilation error, does not match Aircraft requirements.
fly(duck); // OK
}
public interface Lander {
void land();
}
public void landAtMeadow(Lander lander) {...}
public void meadow() {
landAtMeadow(airbus_a380); // OK
landAtMeadow(duck); // OK
landAtMeadow(ladybug); // OK
}
All of them are matching requirements of landAtMeadow so they can be used in that context. Even it may not be possible to land at meadow for airbus_a380 (In other word testing is required) you need to land there in emergency.
Do not forget that landAtMeadow() may have more specific requirements like
public interface Lander { void landAtLimitedArea(int size); }
to say that the space is limited, so if airbus_a380 does not support this method then you have compilation error here.
Java is a strong typed language, so the assignation of an instance to an interface typed variable must be validated at compile time. This can only be done by explicitly declared interface implementations.
As others have said, this is a basic characteristic of the Java language. It's there for good reasons, folks who are doing serious largescale programming like it, and there's absolutely no reason to change it.
If it bothers you, I strongly recommend that you find another language that is more weakly typed and use that instead. There are a fair number of languages these days which can be compiled into Java bytecodes and used in a Java environment, so you might not even have to give up the flexibility of being able to run in a JVM.
My friend In a strongly typed languages, for ex: in C or Java, when a variable or reference is declared, it must be informed to the compiler what data type the variable or reference is of
When a class is declared to implement an interface X then any other method working with interface X is sure that all the necessary methods are implemented in the class (and therefore they do not need to check every time if needed method is implemented). If there was no such declaration, then any method using classes which implement X would need to:
ensure that the class of object whith which the method is working implements all methods necessary (so go through all the methods of the class searching the ones you want every time you expect to work with interface X - instead of doing this once, at compilation).
have many error handling lines of code implemented (what to do, if I expect method A to do something, but method A it is not there at all?)
Static typing adds much to code's safety in general, as many errors are possible to detect at compilation. Why try to change Java from staticaly to dynamicaly typed? There are many dynamicaly typed languages out there, with their pluses and minuses, ready to use (Python, for example).

Categories

Resources