Teacher Java Quiz

From Juneday education
Jump to: navigation, search

Some words on quoted examples

We subscribe to what Kernigan and Plauger wrote in the preface to their book The elements of programming style about quoting authors on code which could have been written differently. Let us paraphrase what Kernigan and Plauger wrote:

We intend no criticism of text book authors or teachers of programming, either individually or as a class. Shortcomings only show that we are all humans, and that under the pressure of a large, intellectual demanding task like writing a program or a book, it is much too easy to do somethings imperfectly.

And we, the authors of this wiki, have no doubts that some of our own writings could and will be used as "bad" examples by other critically thinking teachers! We hope that you will find errors in our own writings and report them to us so that we can correct them. And we won't hesitate to credit whoever finds room for improvement, nor to publicly admit what was wrong and why it was a good idea to improve it.

And we don't have any claims of even coming close to Kernigan or Plauger when it comes to skills in programming or the style therof. We do however share their ideas on lending code from public sources in order to make a point. The point not being to point fingers at other authors (or in our case teachers), but to start a discussion on room for improvement while being humble enough to realize that we too, probably are guilty of similar mistakes.

Q1

Which of the following is true about Java variables (reference variables and primitive type variables alike):

A Variables get default values

B Uninitialized variables get the UNDEFINED value

C Uninitialized variables get the null value

D Some variables get default values, others don't

Expand using link to the right to see the answer with an explanation.

A is incorrect, because only some contexts ensure that variables get default values. Stating that variables get default values is therefore too broad a statement and false.

B There is no UNDEFINED value in Java. An uninitialized variable is simply that, uninitialized. Any attempt to use an uninitialized variable will render a compiler error, and is therefore not Java code. Only code that compiles can be considered Java code.

C is incorrect, because of the reasons stated in A, and also because even those variables that do get default values, get different default values depending on whether they are reference type variables (in which case they do get the null value) or if they are of a primitive type. Se the explanation for alternative D below.

D is correct. Motivation: Some variables get default values. This applies to instance variables and class variables and elements of new arrays (created with e.g. new int[4]).

Variables that do get default values get the following default values:

  • Reference type variables get the value null
  • Primitive type variables of a numeric integer type (byte, short, int, long) get the value 0
  • Primitive type variables of a floating-point type (float, double) get the value 0.0
  • Primitive boolean variables get the value false
  • Primitive char variables get the value '\u0000' (or 0 if cast to an int)

Local variables (variables declared as parameters or inside the block of a constructor or method) do not get any default values.

Discussion

Is it so important not to make broad sweeping statements about the rules and semantics of the programming language? Our answer starts with a counter question: "Is is ever harmful to the students to make correct statements?". We've seen the statement "Java variables get default values" in lecture presentations, books and online.

Some might argue, "Yes, but when I show that slide, I make it clear when this applies and when it doesn't." We've heard that argument too. The problem is, however, if you have to correct yourself when showing such a slide, then there is something wrong with the slide. What if students don't listen? What if students are not present when you make the correction or additional statements? We've seen that students who read a statement such as the above, take it for granted that the printed statement is correct. Just like when we show bad code, in order to make a point, there is always a chance that students do like the code says, not like the teacher says.

An example of a too broad statement about default values in Java can be found at Uppsala University:

Vid en deklaration

int x;

får x defaultvärde (i detta fall, 0)

Några viktiga skillnader mot C/C++:

Variabler har defaultvärden.

Storlek för olika typer är definierat i språket.

Språket definierar typerna boolean, byte och char.

https://www.it.uu.se/edu/course/homepage/oopjava/vt17/html/f02-java.html

Note: We show the quote as an example to prove a point. We have no opinions on the source of the quote from other perspectives.

Q2

Will the following compile? And if not, what would the compiler error message be?

  public static void main(String[] args) {
    int i;
    if (args.length == 0) {
      i = 0;
    }
    System.out.println(i);
  }

A It compiles without any warnings or errors

B It compiles with a warning: "variable i might not have been initialized"

C It doesn't compile with the error "variable i might not have been initialized"

D It compiles but will throw a NullPointerException at runtime

Expand using link to the right to see the answer with an explanation.

The answer is that it doesn't compile, because local variables are not allowed to be used before the compiler can verify that they have been initialized in all branches leading up to the use of the variable.

A is wrong, because attempts to use a local variable before initialization is a compilation error, and therefore not valid Java code.

B is wrong for the same reason as A.

C is correct for the same reason as A.

D is wrong for the same reasons as A. Additionally, a NullPointerException would have been weird, since i is of the primitive type int.

We'd like to point out that we have seen people answering incorrectly to the first question, thinking that all variables get default values, and still be able to answer correctly to this question. We find that interesting. This shows how easy it is to create a cognitive dissonance for observant students, if we are not careful. It is probably confusing to most students to learn that variables get default values but sometimes can't be used without explicit initialization.

Q3

The Java primitive char type is typically used:

A for storing a unicode character

B for storing 16-bit unsigned integers representing UTF-16 code units

C the same as in the C programming language, for storing integer values and are usually eight bits in size

D for storing a 16 bit unsigned integer value

Expand using link to the right to see the answer with an explanation.

A is wrong, because "a unicode character" is not a datatype. Characters need to be encoded in order to make sense to a computer.

B is correct, and is actually a quote from the Java Language Specification. This is because Java represent text as 16 bit unsigned UTF-16 code points. In other words, chars in a String are encoded with UTF-16. A consequence of this is that some characters take two chars to represent. This is because some characters are encoded with a pair of code points. To see this in action, try this:

To write the character: 𝛺 in Java, we can create a String:

String omega = "𝛺";

While this clearly is one "character" (MATHEMATICAL ITALIC CAPITAL OMEGA), the string's length is 2. It consists of two chars: {'\uD835', '\uDEFA'}. This can easily be verified:

String omega = "𝛺";
System.out.println(omega.length()); // 2
System.out.println(Integer.toHexString(omega.charAt(0))); // d835
System.out.println(Integer.toHexString(omega.charAt(1))); // defa

So, a Java char is not "a unicode character". A unicode character is just that, a character in the unicode table, something we can print. Such a character can sometimes be represented by a single Java char, and other times it requires two Java chars, because Java encodes characters using UTF-16. The two characters needed for 𝛺 are called a surrogate pair.

C is wrong, because of the reasons stated in B. Additionally, the Java primitive types are always of a fixed bit length. The char type is always 16 bits.

D is wrong, because the questions states "is typically used". The char type is typically used for representing a character (or a part of a surrogate pair which together will represent a character). Many think that using char as a datatype for unsigned 16 bit integers is bad style. Even if it could be used as such. But the typical use is for representing characters (which sometimes requires a pair of chars as shown above).

Q4

Files in a file system are often divided into two groups, "binary files" and "(plain) text files". What is the difference between a so called text file and a so called binary file?

A A text file stores plain text in the file, as a sequence of characters which needs no translation or interpretation, while binary files store binary sequences (a sequence of binary numbers) which has to be decoded to be useful

B Text files can be read by most programs because the computer can interpret most characters while binary files require special programs in order for the computer to make sense of the binary content

C Text files must have one of a set of known file suffices; .txt, .html, .xml, .java, .c etc. Binary files can have any file suffix, since there are new file types invented all the time.

D From the computer's point of view, there is no difference between a text file and a binary file. In fact, text files are a form of binary file. What makes a text file a text file, is that the binary content can be interpreted using a predefined character set where each character has a defined numeric value, or where the byte stream can be otherwise interpreted to a sequence of characters from some character repertoire using a character encoding (where unique numbers are assigned to each character in the repertoire).

Expand using link to the right to see the answer with an explanation.

Answer: 'D' is correct.

'A' is wrong, because all files are binary sequences (except empty files perhaps).

'B' is wrong, because computers can't interpret characters or text at all. Programs that can interpret characters from binary sequences can be written, on the other hand. Compilers and text editors are examples of such programs.

'C' is wrong, because file suffices have nothing to do with file contents. Some operating systems let the user bind certain default actions based on file suffices, however. But this is a very bad idea, since an MP3 file with the suffice .txt should be bound to actions involving the handling (perhaps playback) of MP3 files based on the contents of the file, not based on the file suffix. Opening such an MP3 file in a text editor is rarely the action the user expects or wants.

'D' is correct, because all files are sequences of bits (binary sequences). Text files are no exception. The storage media has no special way of storing the bits representing sequences of characters, just as it has no special way of storing bits representing MP3 encoded music, or any other file type. It stores bits. Any file needs a piece of software to make sense.

Q5

In the memory used by the JVM (internal representation), a Java byte variable takes up

A 1/4 the memory of a Java int variable

B 2/4 the memory of a Java int variable

C 2 times the memory of a Java int variable

D The same as the memory of a Java int variable

Expand using link to the right to see the answer with an explanation.

Answer: 'D' is correct, if we look at the specification for the JVM.

'A', 'B', and, 'C' are incorrect because internally, values of the type byte, char, and, short are represented as int values by the JVM as per § 3.2 of the JVM specification:

The lack of direct support for byte, char, and short types in the Java Virtual Machine is not particularly painful, because values of those types are internally promoted to int (byte and short are sign-extended to int, char is zero-extended). Operations on byte, char, and short data can thus be done using int instructions. The only additional cost is that of truncating the values of int operations to valid ranges.

We do not know if there are any JVMs that really implement the smaller types as occupying less memory internally, but if there are, they do not follow the JVM specification.

The reason for using smaller types byte, char, and, short are for type safety and not memory efficiency. Internally, a byte take up the same space as an int with the added cost of truncating values. This means that using a byte could be more costly than using an int since the JVM must sign-extend the values, or truncate the values to int internally.

The famous tables of types versus amount of bits in books and teaching materials are not about memory footprints. They are about the range of values possible to store in the types respectively. Integer values are stored in Java as two's complement bit patterns, which also dictates the rules for overflow and underflow.

How large an int internally in the JVM actually is, is not specified (as far as we can see). All we know is that the smaller types are widened to the same size as an int when used internally by the JVM.

Note that arrays of the various types might be more compact than that of int values, though. This would be so if the array values are contiguous in the memory layout, so that an offset could be used. When we tried, however, on Ubuntu 64 bits and Open JDK 1.8.0_181, we could see no significant difference in size of a 1000 element long array of int and byte respectively.

Q5

A constructor for a class which takes no arguments and basically does nothing, e.g. looks something like this:

public MyClass() {

}

What is this type of constructor usually called?

A Empty constructor

B Default constructor

C Parameter-less constructor or no-arguments constructor

D Automatic constructor

Expand using link to the right to see the answer with an explanation.

Answer: C is correct in so far that if it had a name, this would be the possible names. The answers in C are actually correct descriptions of the constructor, rather than a name.

A is wrong, because it doesn't correctly describe the constructor. We could have a constructor which takes argument but has an empty body. So empty is rather vague.

B is wrong, because the default constructor is the constructor the compiler injects into the class file if we write no constructors ourselves. That constructor is a no-arguments constructor, but it isn't empty. It contains a call to super() which we easily can verify:

$ cat Default.java 
public class Default {

}
$ javac Default.java
$ javap -c Default
Compiled from "Default.java"
public class Default {
  public Default();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return
}

As you see from the output from javap -s, there was a constructor added which calls the no-arguments constructor in class Object (which in this case is the same as if we'd written super() since our class implicitly extends java.lang.Object).

Unfortunately, it is not uncommon that people call the parameter-less constructor "the default constructor", which is wrong and probably confusing to more people than us. We don't know why this is. Perhaps people confuse it with the default constructor because they look similar in byte code (except for the call to super()).

Here's an example of confusing terminology surrounding constructors:

"No-argument constructor: A constructor that has no parameter is known as default constructor. If we don’t define a constructor in a class, then compiler creates default constructor(with no arguments) for the class. And if we write a constructor with arguments or no-argument then compiler does not create default constructor. Default constructor provides the default values to the object like 0, null etc. depending on the type."

https://www.geeksforgeeks.org/constructors-in-java/

The above quote is incorrect and confusing since it first says that "A constructor that has no parameter is known as default constructor", and later says that the compiler "creates default constructor(sic!)". Further on, it is incorrect that it would be the default constructor which provides default values. If that were the case, we'd get no default values if we didn't have a default constructor (like when we create a constructor ourselves). Obviously, it is not the constructor, in particular not the perhaps non-existing "default constructor" that gives default values to members of a class.

D is incorrect, and we don't know what "automatic" would imply.

Q6

Since Java 8, rules concerning interfaces have changed quite a bit. Is the following possible?

public interface IMain {
  public static void main(String[] args) {
    System.out.println("Hello no class");
  }
}
$ javac IMain.java && java IMain
Hello no class
$

A No, that's not possible - Interfaces can't have static methods

B No, the main method must reside in a class declaration, not in an interface!

C It is possible to declare the main method in an interface, but you will not be able to run the program since the JVM only accepts the main method if it is declared in a class.

D Yes, it is possible, since interfaces can have static methods since Java 8, so why shouldn't it be possible to declare the main method in an interface?

Expand using link to the right to see the answer with an explanation.

Answer: D is correct.

A is wrong, because interfaces can have static methods since Java 8.

B is wrong, because since interfaces can have static methods since Java 8, and main is a static method, it can be placed in a class or in an interface. It is surely more common to put main inside a class declaration than inside an interface, but both actually work (since Java 8).

C is wrong, because there is no special rule about invoking the main method that says it must reside inside a class, and not inside an interface. It works on our machines (we've tested with OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-0ubuntu0.16.04.1-b13) and with the Windows version Java(TM) SE Runtime Environment (build 1.8.0_191-b12)).

D is correct because of what is said above.

Here's what Brian Goetz, Java Language architect at Oracle said about this, in a reply to a question on StackOverflow:

I think you have the question backwards. The question is not "should main methods be allowed", it is "should we have explicitly disallowed main methods now that static methods are permissible in interfaces" (or, equivalently, exclude interface classes as targets for the java launcher.) This would have been adding extra rules just to exclude something some people perceive as weird (but not dangerous) -- and that's a losing game. You want to define as few new rules as you can reasonably get away with -- because otherwise you get mired in complexity.

Q7

?

Expand using link to the right to see the answer with an explanation.

Q8

?

Expand using link to the right to see the answer with an explanation.

Q9

?

Expand using link to the right to see the answer with an explanation.

Q10

?

Expand using link to the right to see the answer with an explanation.

Q11

?

Expand using link to the right to see the answer with an explanation.