
In early January, I wrote a
post with interesting test puzzles on Java . He caused quite a lot of interest, interesting puzzles still remain, so we will continue.
Immediately answer some questions, the answers to which could be lost in the comments.
First, they asked what to read on the topic. I highly recommend
this booklet . I have not met in Russian, but for some reason it is read much easier than most programming books, so for most it should not be a problem. Secondly, they asked where to get such problems. There is no concrete advice, tasks from various sources, including some nefrishnyh test suites, therefore, as an option, you can pay attention to the sources, references to which are in the comments to the first part of the article.
It so happened that this part got easier tasks, so the results should be better. So, the next test under habrakat (
Be careful, in the second half of the answers and explanations ).
Test
The correct answer is only one, unless otherwise indicated.
')
Question 1
The following code is available:
class Super { public String name = "Tort"; public String getName() { return name; } } class Sub extends Super { public String name = "Habr"; public static void main(String[] args) { Super s = new Sub(); System.out.println(s.name + " " + s.getName()); } }
What will be displayed on the console?
- Habr Tort
- Habr Habr
- Tort Habr
- Tort Tort
- compilation error
Question 2
What we get as a result of the implementation:
boolean b1 = false; boolean b2 = false; if (b2 != b1 = !b2) { System.out.println("YES"); } else { System.out.println("NO"); }
Options:
- compilation error
- runtime error
- will be displayed YES
- NO will be displayed
- nothing will be displayed
Question 3
class Test{ public static void main(String[] args) { String s = "old"; print(s, s = "new"); } static void print(String s1, String s2) { System.out.println(s1 +" "+ s2); } }
As a result, it will be displayed:
- new old
- old new
- new new
- old old
- the code will not compile
Question 4
The following code is available:
class A { A() { print(); } void print() { System.out.println("A"); } } class B extends A { int i = Math.round(3.5f); public static void main(String[] args) { A a = new B(); a.print(); } void print() { System.out.println(i); } }
What will be displayed?
- A 4
- AA
- 0 4
- 4 4
- another answer
Question 5
The following code is available:
class Threader extends Thread { public void run() { System.out.println("In Threader"); } } class Pooler extends Thread { public Pooler(){ } public Pooler(Runnable r) { super( r ); } public void run() { System.out.println("In Pooler"); } } public class TestClass { public static void main(String[] args) { Threader t = new Threader(); Thread h = new Pooler(t); h.start(); } }
As a result of its implementation, we get:
- In pooler
- In threader
- the code will not compile
- runtime error
Question 6
What can be said about this code?
class Habr implements I1, I2{ public void m() { System.out.println("habr"); } public static void main(String[] args) { Habr habr = new Habr(); habr.m(); } } interface I1{ int VALUE = 1; void m(); } interface I2{ int VALUE = 2; void m(); }
Answer Options (MULTIPLE RIGHT ANSWERS POSSIBLE):
- “habr” will be displayed
- You cannot access the VALUE value from the Habr class.
- The code will work only if you delete VALUE in one of the interfaces
- the code will not compile
Question 7
The following code is available:
class Test{ public static void main(String[] args) throws Exception { int[] a = null; int i = a [ m() ]; } public static int m() throws Exception { throw new Exception("Another Exception"); } }
Will this code throw a NullPointerException?
- Yes
- not
Caution - Answers
So, the correct answers are:
- four
- one
- 2
- 3
- one
- one
- 2
Explanations
Question 1
So,
class Super { public String name = "Tort"; public String getName() { return name; } } class Sub extends Super { public String name = "Habr"; public static void main(String[] args) { Super s = new Sub(); System.out.println(s.name + " " + s.getName()); } }
This code will display Tort Tort. It seems like polymorphism should work, and, as you know, the choice is made according to the type of object to which the link refers, and not according to the type of the link itself. But in Java there are redefined methods. And that's all. Overridden fields or constructors simply do not exist. That is, the implementation of the method is always chosen depending on the object to which we refer. Class fields, on the contrary, are selected based on the type of reference, and the override does not work here. Therefore, we get this result.
Question 2
boolean b1 = false; boolean b2 = false; if (b2 != b1 = !b2) { System.out.println("YES"); } else { System.out.println("NO"); }
Here we get a compilation error. It's simple, the question is only in the priority of the operators. ! = has a higher priority, respectively, we get false =! b2, that is, an attempt to assign a value to a constant.
Question 3
class Test{ public static void main(String[] args) { String s = "old"; print(s, s = "new"); } static void print(String s1, String s2) { System.out.println(s1 +" "+ s2); } }
Arguments of methods are calculated from left to right and the fact that in the second argument we assign s a new value does not change anything, since the first argument is already calculated. If the calculation of one of the arguments fails, all other arguments will not be calculated at all.
Question 4
class A { A() { print(); } void print() { System.out.println("A"); } } class B extends A { int i = Math.round(3.5f); public static void main(String[] args) { A a = new B(); a.print(); } void print() { System.out.println(i); } }
The print () method is redefined in class B. Accordingly, the method is selected according to the type of the actual object. When a class B object is created, constructor A is first called, which calls the print () method. Since we are creating a class B object, the print () version of class B is called. At this time, i is not assigned a value, so the default value (0) is output. Well, later on, the initialized value i is displayed. As a result, we get the answer 0 4.
Question 5
class Threader extends Thread { public void run() { System.out.println("In Threader"); } } class Pooler extends Thread { public Pooler(){ } public Pooler(Runnable r) { super( r ); } public void run() { System.out.println("In Pooler"); } } public class TestClass { public static void main(String[] args) { Threader t = new Threader(); Thread h = new Pooler(t); h.start(); } }
It is known that when creating objects of the class Thread, you can pass a Runnable object to the constructor, whose run () method will be executed in a separate thread. Therefore, the expected answer is the “In Threader” output. The reason for non-standard behavior is the run () method in the Pooler class. By redefining the run () method, we thereby lost the default behavior of the Thread class.
Question 6
class Habr implements I1, I2{ public void m() { System.out.println("habr"); } public static void main(String[] args) { Habr habr = new Habr(); habr.m(); } } interface I1{ int VALUE = 1; void m(); } interface I2{ int VALUE = 2; void m(); }
This code is absolutely functional. The fact that the same m () method is present in both interfaces does not create problems, since the implementation will be the same anyway. Harder with the VALUE field. We cannot directly address it, as ambiguity will arise. But this can be done, for example, as follows:
((I1) habr) .VALUE;
After bringing the object to one of the interfaces, we get access to fields that previously could not use.
Question 7
The following code is available:
class Test{ public static void main(String[] args) throws Exception { int[] a = null; int i = a [ m() ]; } public static int m() throws Exception { throw new Exception("Another Exception"); } }
In this case, a NullPointerException will not occur, since any action with an array, including checking for the existence of an object, occurs only after the element index has been fully calculated.
The situation becomes more interesting if we assign something to an element of the array. For example, given the code:
int i = 0 ; int[] arr = {1, 2} ; arr[i] = i = 6 ;
As a rule, multiple assignments are calculated from right to left. But indexes are the exception. In this case, the index (arr [0]) will be calculated first, and only then the variable i will be assigned a new value.
Thank you all for your attention. Probably in this format I will not write anymore, I plan to move on to the consideration of individual low-lighted subjects in the books.