⬆️ ⬇️

Tricky java tasks

Most recently, I passed OCA Java SE 7 Programmer I. During the preparation, I managed to solve a huge number of tasks and extract many fine points of the language from them. The most interesting and deft - saved for the future. And now I have a small personal collection, the best part of which I will describe here.



In a wonderful article Do you know JAVA,% username% and its second part, the author also shared his experience after preparation. However, I came to the conclusion that I can add something of my own. And this article was born.





Tasks

So, let's begin. I broke all the tricks into small puzzles that I made for you. The subtleties of the language stand out in their pure form - without unnecessary bells and whistles, as it was in the tests. I also recommend that you first answer the question with an accuracy of a symbol and write it down somewhere , and then watch the correct answer. I wonder how many users who solved this test will answer more than half? And do not forget that all these examples are focused on Java 7.

')

1) Does this code compile and if so, what will the output be?

long year = 201l; System.out.print(year); 
Answer
201
Explanation
I specifically turned off the backlight - so that there was no noticeable trick. Otherwise, the last letter would visually stand out - and in it the whole point of the question.



In English, the lower case letter l is very similar to the number 1. And by this example I want to warn you - never use l small for long literals , although Java allows it. And do not use it at all, where potentially there can be one. Just make use of the uppercase L, as most programmers do.



If you look closely, you will notice that the units are visually a little different. Quite a bit. But you and I want to think everything through, isn’t it?



The conclusion will be - 201 , not 201 1 , as it may seem at first glance.


2) Will this code be compiled and if so, what will be the output?

 int[][] array = {{1, 2, 3}, {0, 0, 0,},}; System.out.println(Arrays.deepToString(array)); 
Answer
[[1, 2, 3], [0, 0, 0]]
Explanation
Fallacy is usually caused by two “extra” commas at the end.



When I first saw such code in one of the tests, I firmly decided that the code would not compile - and it turned out to be wrong. Some of you may assume that the non-specified items will be filled with the default value — and that will be wrong too.



And the output will be simple - [[1, 2, 3], [0, 0, 0]] . It turns out that the compiler simply ignores one extra comma at the end of the array. And exactly one - two in a row will already cause a compilation error.



I easily described this situation in the language specification - A trailing comma may appear after initial expression and is ignored .



And in practice, it is made for convenience when manually copying from one array to another. If the compiler did not allow to put an extra comma, then in some cases you would have to add a comma at the end, when we copy and paste values ​​from one array to the end of another - or delete the extra at the end.



3) Does this code compile and if so, what will the output be?

 double $ = 0XD_EP2F; System.out.print($); 
Answer
888.0
Explanation
You will probably be sure that this code will not compile. And no! he is quite working.



When I was learning Java, I immediately noticed that something could be done from underscores and exponential forms for HEX. This example is, of course, not for use in real projects - but for training your knowledge. I think this is the most difficult example and highlight of the article. The first two were a light workout. Has anyone answered correctly the first time?



In this example there are two interesting points. The first is the name of the variable. Calling a variable a dollar is quite funny. But never, never do that in real projects . Although the compiler does not prohibit such an approach - it is not recommended, as the dollar is used for technical purposes. For example, to name anonymous and nested classes. MyClass $ MyInnerClass, or MyClass $ 1. And you can easily arrange the collapse of names - one class simply called MyClass $ MyInnerClass, and the other - MyClass with the nested MyInnerClass - and they will have the same name. So it is not recommended to include the dollar in your variables.



This code is also quite correct.
 double _ = 8.0; 


And now let's look at the second point - the literal itself. I did it as best I could. For a start, it's easy to see that this number is written in hexadecimal form. But she admits only A, B, C, D, E, F as letters - you think. Where does P come from then? And where does the underscore sign?



Everything in order. F at the end means that this literal is of type float. And here it is automatically converted to double type. Next, a very interesting point - P2. If we want to write a hexadecimal number in an exponential form, we cannot use E + N, because E can be used in the number itself and ambiguity can occur. But no one bothers us to use BinaryExponentIndicator - we specify p and degree. The number will be multiplied by 2 to the specified power. In this case - on 4.



But the underscore character is a very convenient innovation of Java 7. We can simply insert it into a number and separate it, for example, digits, or group numbers. The compiler simply cuts it - it is needed for more convenient reading, no more.



So, to accurately answer the question, we need to remember that System.out.print displays a double variable in regular, decimal form. Consequently, we need to translate from hex to decimal. This is a completely trivial task. DE 16 = 222 10 . Next, multiply 222 by 2 2 and get 888. Finally, do not forget that for the type of double, in the absence of the fractional part, a point and zero are added. Here is the answer - 888.0 .



4) Does this code compile and if so, what will the output be?

 public class Main{; public static void main(String[] args) { System.out.println(new Main().$_$()[2]); } ;short $_$()[] {{{ return new short[007]; }}}; }; 
Answer
0
Explanation
The first thing that catches your eye is the use of semicolons where they can not be used. For example, after class declaration (as in C ++). Or between class members. Why the compiler gave the opportunity to put them there - I never found out. But it is quite acceptable.



Method name is a valid ID. But the return type here is not short, but an array from short. The compiler allows 2 forms of array declaration - square brackets before and after the identifier. And the first case is intended just for the method. And what if you try the second case for the method? It is also correct, but it looks awful, so never use it in real projects . But there is such an opportunity.



Further, inside the method there are just two nested blocks of code that can be safely removed. And in the end, the method simply returns an array of short 7 elements long, which is initialized with zeros and the element with index 2 is 0. Oh yes, 007 is an octal literal. But this also does not affect anything.



5) Will this code be compiled, and if so, what will the output be?

 public class Main { public static void main(String[] args) { ((Main) null).hara(); } static void hara() { System.out.println("Hello habrahabr!"); } } 
Answer
Hello habrahabr!
Explanation
Attentive readers will notice that the name of the method contains the Russian letter B. Not only does Java allow you to completely write the name of identifiers in languages ​​other than English, so we can also mix letters from different languages.



The important point I wanted to convey to you is that you can accidentally type the wrong character from another language and then look for the error for a long and painful time. For example, English a and Russian a are visually indistinguishable (at least in this font). If the unit can be distinguished from l at least somehow, then everything is much worse. Imagine a situation - for some reason you accidentally typed a Russian letter instead of an English one in the name of a class or method. Or, more likely, they edited an already existing Latin name with a Russian layout. There are quite a few similar letters between these languages, so there is a chance for a mistake. Autocomplete will insert an international ID and everything will work fine. But if you try to call a method or get a class through reflection, you will get an error that will not be so easy to detect. Rather, you will look for it in another, since the names will visually match - you lose time and energy.



I would like to add one more example, in which two identical identifiers on the appearance will contain externally identical letters from different alphabets, but the code is different and therefore the identifiers will also be different. And make explain why the code causes a compilation error. But it would be too cruel - seemingly not catch a catch.



Next - we call the static method rather original - cast null to the type Main. And it will not cause a runtime error! The fact is that the call of static methods is resolved at the compilation stage and depends only on the type of the object.



In the comments to this article, user Yurevich1 gave an example from a real project:

Once in the project I set the class variable “c” in Russian. I killed an hour somewhere to understand what the error is and the project in another part of the code swears at the same variable c, which is already in English.




6) Does this code compile and if so, what will the output be?

 Byte[] Byte[] = {{0}}; System.out.println(Byte); System.out.println(Byte.class); System.out.println(Byte.length); System.out.println(new Byte("8")); 
Answer
[[Ljava.lang.Byte; @ 6f171e30 (the hash may be different )

class java.lang.Byte

one

eight
Explanation
So, here's another sample code that at first glance is misleading. To begin with, you would be confused by the seemingly following two consecutive declarations of an array of byte wrappers. However, if you have carefully studied the language, you should know that there are two ways to declare an array — with square brackets before and after the name. Moreover, no one bothers us to use these two methods at the same time - before you is just a two-dimensional array.



Next you should be confused by the name of the array, which completely coincides with the name of the class. Java allows you to call local variables classes of the standard library, while they will overlap classes. However, Java compiler is smart. Very smart. He will figure out that after the new operator only the class can follow, and before the .class too. And in that context, the class Byte will be implied, although the instance name should overlap it.





Results

I like Java for its hard standardization. The specification defines almost all the details with very high accuracy. And that means - having studied these subtleties once - you can work with them everywhere.



I want to add that the screen code above the cut is taken from IDEA . I developed the backlight scheme myself and use its advantages to the maximum. If someone liked - I can throw.



I was preparing for several different testing systems. For starters, a good site would be Quizful . The Java Fundamentals and Java Intermediate Tests contain a very large number of useful tasks. Further, the tests from ExamLab are very good - I drove the SCJP 6 over them. And finally - for the exam itself - Enthuware .



After passing many tests and solving problems “in my mind”, I was pleasantly surprised at how comfortable and effective the writing of the code was. Tests are very well systematized and organize knowledge. I began to anticipate many mistakes in my mind, and also to choose the best solutions. And I did not regret that I had learned some of the API, although at first I thought that I should not remember the names of methods and classes by heart. I consider Java as one of the best languages ​​in the world and recommend tests for in-depth study. A Java SE 7 Programmer I was not at all difficult - easily scored 96 out of 100 points. Who is going to take - I can give a couple of tips - write in a personal .

Source: https://habr.com/ru/post/203796/



All Articles