2 “simple” Java questions

Greetings, dear reader.
Java is an interesting and beautiful language. But sometimes it can be written on it that it’s better not to see it. But it’s still useful to know what happens in such curves, cases.
Fans of clean code, please excuse me.
Once upon a time there were a couple of articles on the hub -
Part 1 , Part 2
They are very interesting, but, unfortunately, the author did not continue.
I present to your attention 2 more tasks (there wasn’t enough strength for more. It turns out that writing articles is not so easy.)
At the end of the article, of course, there will be answers with explanations, as well as additional tasks for the strongest.
The first task is taken cleanly from the wonderful book by Joshua Bloch's Java Puzzlers . The book does not teach you how to write code (rather, on the contrary, how it is not necessary and why), but personally it was wildly interesting for me to read it. Just for fun. Recommend.
So let's get started.
Conditions
1. Execution cannot be pardoned
public class A {
public static class X {
public static class Y {
public static String Z = "life is good";
}
public static C Y;
}
public static class C {
public static String Z = "life is pain";
}
public static void main(String[] args) {
System.out.println(X.Y.Z);
}
}
What will happen?
- Compile error
- Runtime error
- Will bring life is good
- Will bring life is pain
2. Generics are such generics
public class B {
public static T foo() {
try {
return (T) new Integer(42);
} catch (ClassCastException e) {
return (T) "habr";
}
}
public static void main(String[] args) {
System.out.println(B.foo());
}
}
What will happen?
- Compile error
- Runtime error
- Output 42
- Will output habr
And now the correct answers:
1. Execution cannot be pardoned
public class A {
public static class X {
public static class Y {
public static String Z = "life is good";
}
public static C Y;
}
public static class C {
public static String Z = "life is pain";
}
public static void main(String[] args) {
System.out.println(X.Y.Z);
}
}
Print life is painEverything is wild, but simple. Yes, jls allows this. Priority is always on the field.
Much more interesting is how to get around this and bring life to good. I know three solutions:
- reflection api
- import xy
- Statics can be accessed through an instance: (new XY ()). Z
Quest for the top five
The latter method is good, but it requires creating an object, which is bad. Add a private constructor. And now weak? (without reflection and static import)
public static class X {
public static class Y {
private Y() {}
public static String Z = "life is good";
}
public static C Y;
}
Answer:Hidden text
((X.Y)null).Z; // подберите свои челюсти, это Java.
2. Generics are such generics
public class B {
public static T foo() {
try {
return (T) new Integer(42);
} catch (ClassCastException e) {
return (T) "habr";
}
}
public static void main(String[] args) {
System.out.println(B.foo());
}
}
Runtime error , or more precisely, a ClassCastException So, we all know that in java generics are nothing more than syntactic sugar that
Let's look carefully at the code:
System.out.println(B.foo());
The compiler understands that the type of the argument is String, and therefore substitutes the most suitable println:
public void println(String x)
It is important that determining which version of the overloaded method to use is a compilation-level task, not a runtime.
Move on.
return (T) new Integer(42);
Cast occurs in runtime, at a time when generics are no longer there.
What will happen?
Nothing. Integer will just return.
Well, we arrived - we called printf, which takes String, and passed Integer to it.
Lessons for the future
- Don't do that
- There is more than println in the world that accepts Object
- A generic type cast is a crutch
Quest for the top five
Implement a method that throws an arbitrary Throwable (including a checked exception) that does not require either thows or try-catch:
public static void throwWithoutCheck(Throwable t) {
// Никаких проверок, только хардкор. Хочу throwWithoutCheck(new Exception()) - и никаких throws!
}
Answer:Hidden text
UPD:
There are still ways to throw an execution without checking. They were not meant as an answer, but, let's say, more “honest”:
Note that stop is @deprecated. The concept of working with streams has undergone significant changes, thegrass has become greener, and the air is cleaner .
As an argument to Stop, you can pass the "reason" for the stop. It is clear that in Java, in principle, you cannot conclude this in a try catch block, I hope everything is clear here.
Thanks to orionll for an example .
Or:
Here, everything is also clear, just so you can’t work with Unsafe and, in this case, everything is completely justified.
Thanks mishadoff for the example .
private static void castAndThrow(Throwable t) throws T {
throw (T) t;
}
public static void throwWithoutCheck(Throwable t) {
B.castAndThrow(t);
}
UPD:
There are still ways to throw an execution without checking. They were not meant as an answer, but, let's say, more “honest”:
Thread.currentThread().stop(new IOException());
Note that stop is @deprecated. The concept of working with streams has undergone significant changes, the
As an argument to Stop, you can pass the "reason" for the stop. It is clear that in Java, in principle, you cannot conclude this in a try catch block, I hope everything is clear here.
Thanks to orionll for an example .
Or:
Unsafe.getUnsafe().throwException(new IOException());
Here, everything is also clear, just so you can’t work with Unsafe and, in this case, everything is completely justified.
Thanks mishadoff for the example .