4 Declarations and Access Control



In Java, arrays are objects. Each array object has a final field named length that stores the size of the array.



Java allows arrays of length zero. Such an array is passed as an argument to the main() method when a Java program is run without any program arguments.



The [] notation can be placed both before and after the variable name in an array declaration. Multidimensional arrays are created by constructing arrays that can contain references to other arrays. The expression new int[4][] will create an array of length 4, which can contain references to arrays of int values. The expression new int[4][4] will create the same array, but will in addition create four more arrays, each containing four int values. References to each of these arrays are stored in the first array. The expression int[][4] will not work, because the arrays for the dimensions must be created from left to right.


(b) and (e)

The size of the array cannot be specified as in (b) and (e). The size of the array is given implicitly by the initialization code. The size of the array is never specified in the declaration of an array reference. The size of an array is always associated with the array instance, not the array reference.



The array declaration is valid and will declare and initialize an array of length 20 containing int values. All the values of the array are initialized to their default value of 0. The for loop will print all the values in the array, that is, it will print 0 twenty times.



The program will type "no arguments" and "four arguments" when called with 0 and 3 arguments, respectively. When the program is called with no arguments, the args array will be of length zero. The program will in this case type "no arguments". When the program is called with three arguments, the args array will have length 3. Using the index 3 on the numbers array will retrieve the string "four", because the start index is 0.



The program will print "0 false 0 null" when run. All the instance variables, including the array element, will be initialized to their default values. When concatenated with a string, the values are converted to their string representation. Notice that the null pointer is converted to the string "null" rather than throwing a NullPointerException.



Only (b) is a valid method declaration. Methods must specify a return type or are declared void. This makes (d) and (e) invalid. Methods must specify a list of zero or more comma-separated parameters delimited by ( ). The keyword void is not a valid type for a parameter. This makes (a) and (c) invalid.


(a), (b), and (e)

Non-static methods have an implicit this object reference. The this reference cannot be changed, as shown in (c). The this reference can be used in a non-static context to refer to both instance and static members. However, it cannot be used to refer to local variables, as shown in (d).


(a) and (d)

The first and the third pairs of methods will compile correctly. The second pair of methods will not compile correctly, since their method signatures do not differ. The compiler has no way of differentiating between the two methods. Note that return type and the names of the parameters are not a part of the method signatures. Both methods in the first pair are named fly and, therefore, overload this method name. The methods in pair three do not overload the method name glide, since only one method has that name. The method named Glide is distinct from the method named glide, as identifiers in Java are case sensitive.



A constructor cannot specify any return type, not even void. A constructor cannot be final, static or abstract.


(b) and (e)

A constructor can be declared private, but this means that this constructor can only be used within the class. Constructors need not initialize all the fields of the class. A field will be assigned a default value if not explicitly initialized. A constructor is non-static, and as such it can directly access both the static and non-static members of the class.



A compilation error will occur at (3), since the class does not have a constructor accepting a single argument of type int. The declaration at (1) declares a method, not a constructor, since it is declared as void. The method happens to have the same name as the class, but that is irrelevant. The class has an implicit default constructor since the class contains no constructor declarations. This constructor is invoked to create a MyClass object at (2).


(c) and (d)

A class or interface name can be referred to by using either its fully qualified name or its simple name. Using the fully qualified name will always work, but in order to use the simple name it has to be imported. By importing net.basemaster.* all the type names from the package net.basemaster will be imported and can now be referred to using simple names. Importing net.* will not import the subpackage basemaster.



A class is uninstantiable if the class is declared abstract. The declaration of an abstract method cannot provide an implementation. The declaration of a non-abstract method must provide an implementation. If any method in a class is declared abstract, then the class must be declared abstract. Definition (d) is not valid since it omits the class keyword.



A class can be extended unless it is declared final. For classes, final means it cannot be extended, while for methods, final means it cannot be overridden in a subclass. A nested static class, (d), can be extended. A private member class, (f), can also be extended. The keyword native can only be used for methods, not for classes and fields.


(b) and (d)

Outside the package, member j is accessible to any class, whereas member k is only accessible to subclasses of MyClass.

Field i has package accessibility and is only accessible by classes inside the package. Field j has public accessibility and is accessible from anywhere. Field k has protected accessibility and is accessible from any class inside the package and from subclasses anywhere. Field l has private accessibility and is only accessible within its own class.



The default accessibility for members is more restrictive than protected accessibility, but less restrictive than private. Members with default accessibility are only accessible within the class itself and from classes in the same package. Protected members are in addition accessible from subclasses anywhere. Members with private accessibility are only accessible within the class itself.



A private member is only accessible by code from within the class of the member. If no accessibility modifier has been specified, a member has default accessibility, also known as package accessibility. The keyword default is not an accessibility modifier, and its only use is as a label in a switch statement. Members with package accessibility are only accessible from classes in the same package. Subclasses outside the package cannot access members with default accessibility.


(b) and (e)

You cannot specify accessibility of local variables. They are accessible only within the block in which they are declared.

Objects themselves do not have any accessibility, only references to objects do. If no accessibility modifier (public, protected, or private) is given in the member declaration of a class, the member is only accessible to classes in the same package. A class does not have access to members with default accessibility declared in a superclass, unless both classes are in the same package. Inheritance has no consequence with respect to accessing members with default accessibility in the same package. Local variables cannot be declared static or given an accessibility modifier.



The line void k() { i++; } can be re-inserted without introducing errors. Re-inserting line (1) will cause the compilation to fail, since MyOtherClass will try to override a final method. Re-inserting line (2) will fail, since MyOtherClass will no longer have a default constructor. The main() method needs to call the default constructor. Re-inserting line (3) will work without any problems, but re-inserting line (4) will fail, since the method will try to access a private member of the superclass.



An object reference is needed to access non-static members. Static methods do not have the implicit object reference this, and must always supply an explicit object reference when referring to non-static members. The static method main() refers legally to the non-static method func() using the reference variable ref. Static members are accessible both from static and non-static methods, using their simple names.



Local variables can have the same name as member variables. The local variables will simply shadow the member variables with the same names. Declaration (4) defines a static method that tries to access a variable named a, which is not locally declared. Since the method is static, this access will only be valid if variable a is declared static within the class. Therefore, declarations (1) and (4) cannot occur in the same class definition, while declarations (2) and (4) can.



The keyword this can only be used in non-static code, like in non-static methods. Only one occurrence of each static variable of a class is created. This occurrence is shared among all the objects of the class (or for that matter, by other clients). Local variables are only accessible within the local scope, regardless of whether the local scope is defined within a static context.



The variable k cannot be declared synchronized. Only methods and code blocks can be synchronized.



The declaration abstract int t; is not legal. Keywords static and final are valid modifiers for both field and method declarations. The modifiers abstract and native are only valid for methods.


(a) and (c)

Abstract classes can contain both final methods and non-abstract methods. Non-abstract classes cannot, however, contain abstract methods. Nor can abstract classes be final. Only methods can be declared native.



The transient keyword signifies that the fields should not be stored when objects are serialized. Constructors cannot be declared abstract. When an array object is created, as in (c), the elements in the array object are assigned the default value corresponding to the type of the elements. Whether the reference variable denoting the array object is a local or a member variable is irrelevant. Abstract methods from a superclass need not be implemented by a subclass. The subclass must then be declared abstract.