User Konstantin
Konstantin
Level 36
Odesa

Exploring questions and answers from a job interview for a Java developer position. Part 5

Published in the Random group
Hello, hello! Java developers are in great demand today. Of course, I can't provide you with a job opening, but I will try to help you gain some new knowledge and fill some gaps. So let's continue our review of Java developer interview questions. You can find links to the previous parts of the review at the end of the article. Exploring questions and answers from a job interview for a Java developer position. Part 5 - 1

39. What are the access modifiers in Java? Name them. What are they used for?

I previously covered access modifiers in a question about the elements of Java used to achieve encapsulation. But still, I'll remind you. Access modifiers in Java are keywords that describe the level of access granted to a particular Java component. The following access modifiers exist:
  • public — an element marked with this modifier is public. In other words, fields and methods, and classes declared with the public modifier are visible to other classes both in their own package and in external packages;
  • protected — an element marked with this modifier is accessible from anywhere in its own class in the current package or derived classes, even if they are in other packages;
  • default (or no modifier at all) applies implicitly when no access modifier is indicated. It is similar to the previous one, except that it is visible in derived classes found in other packages;
  • private — this is the most private of all modifiers. It allows access to an element only within the current class.

40. Name the main features of static and non-static methods

The main difference is that static methods belong to a class. In fact, you don't need to create an instance of this class — static methods can be called just from the class type. For example, suppose we have a static method for petting a cat:

public class CatService {
   public static void petTheCat(Cat cat) {
       System.out.println("Pet the cat: " + cat.getName());
   }
We do not need an instance of the CatService class to call it:

Cat cat = new Cat(7, "Bobby");
CatService.petTheCat(cat);
By contrast, ordinary methods are bound (belong) to an object. To call them, you must have an instance (object) on which the method will be called. For example, suppose our cat has a non-static method meow():

class Cat {
   public void meow() {
       System.out.println("Meow! Meow! Meow!");
   }
To call this method, we need a specific instance of a cat:

Cat cat = new Cat(7, "Bobby");
cat.meow();

41. What are the main restrictions that apply to static and non-static methods?

As I said earlier, the main limitation of an ordinary (non-static) method is that there must always be some instance on which the method is called. But a static method does not require this. Additionally, a static method cannot use the this reference to elements of an object since now a current object exists for the method.

42. What does the static keyword mean? Can a static method be overridden or overloaded?

An element marked with the static keyword does not belong to an instance of a class but rather to the class itself. It is loaded when the class itself is loaded. Static elements are the same for the entire program, while non-static elements are the same only for a specific object. The following elements can be static:
  • fields of a class;
  • initialization block of a class;
  • a method of a class;
  • nested classes of a class (of course, this is also a tautology).
A static method cannot be overridden: it belongs to the class and is not inherited, but at the same time, it can be overloaded.

43. Can a method be static and abstract at the same time?

I already answered this in a previous article: a method cannot be abstract and static at the same time. If a method is abstract, that implies that it must be overridden in a child class. But a static method belongs to the class, and it cannot be overridden. This creates a contradiction, which the compiler will notice and get upset about. If you find yourself in this situation, you should seriously think about the correctness of your application's architecture (hint: something is clearly wrong with it). Exploring questions and answers from a job interview for a Java developer position. Part 5 - 2

44. Can static methods be used in the middle of non-static methods? And vice versa? Why?

We can use static methods in non-static methods. Nothing prevents that. That said, the opposite is not possible: a static method cannot use a non-static method without referencing a specific instance of the class. Remember, static members of a class do not have access to a this reference: you can have as many concrete objects of the class as you like, and each of them will contain a this reference, which is a self-reference. So how to determine which this reference to use? Uh, you don't. That is why static elements cannot refer to non-static ones without a reference to a specific object. Basically, a static method can use a non-static method only if it has a reference to a specific object. For example, one that came in as a method argument:

public static void petTheCat(Cat cat) {
   System.out.println("Pet the cat: " + cat.getName());
}
Here we see that in the static petTheCat() method calls getName, an ordinary non-static method of a Cat object.

45. What's an interface? Can there be a final interface?

We will recall that Java doesn't have multiple inheritance. Interfaces are something of an alternative to it. An interface is like a very stripped-down class. They define functionality but not a concrete implementation. That task is left to the classes that implement these interfaces. Example of an interface:

public interface Animal {
    void speak();
}
Example of an interface implementation by a class

class Cat implements Animal {
 
   @Override
   public void speak() {
       System.out.println("Meow! Meow! Meow!");
   }
}
Here's the important main thing to know about using interfaces:
  1. Interface methods must only contain a header. They must not have a specific method body, i.e. they must be abstract (though they do not use the abstract keyword). There are exceptions: static methods and default methods, which require a method body.

  2. A class can implement many interfaces (as I said, interfaces are an alternative to multiple inheritance). The interface names are separated by commas in the method header: class Lion implements Animal, Wild.

  3. Interfaces are created using the interface keyword.

  4. When a class implements an interface, we use the implements keyword.

  5. A class that implements a certain interface must implement all of its abstract methods, or must declare itself abstract.

  6. The main purpose of using interfaces is to implement polymorphism (to give an object the ability to take on many forms).

  7. As a rule, access modifiers for methods are not indicated in interfaces: they are public by default, and you cannot specify modifiers other than public. Starting with Java 9, you can use private modifiers on methods.

  8. By default, interface variables are static final. In other words, they are constants — they must always be initialized directly in the interface.

  9. You cannot create an instance of an interface.

The answer to the question of whether interfaces can be final is, of course, no. Indeed, the whole point of having interfaces is for them to be implemented. And as we all remember very well, the final modifier at the class level makes a class not inheritable, and in the case of an interface — not implementable. Why would we need an interface that we cannot implement and use? You're right — we wouldn't! And the compiler agrees. :) Exploring questions and answers from a job interview for a Java developer position. Part 5 - 3Actually, with the introduction of static interface methods since Java 8, there might be a point, but this doesn't change the fact that an interface cannot be final. I've only talked about interfaces very superficially, since this is a broad topic. For more on this, see the articles on interfaces in Java and the difference between abstract classes and interfaces.

46. Where can static fields be initialized?

Static fields can be initialized:
  • immediately upon declaration, using an equals sign (=);
  • in a static initialization block;
  • in a non-static initialization block (but you need to understand that every time an object is created, the static field will be overwritten when this initialization block is executed;
  • in a class constructor. Each time the constructor is called (that is, each time an object is created using this constructor), the field will be overwritten;
  • in static methods;
  • in non-static methods;
  • in nested static and non-static, local, and anonymous classes.

47. What are anonymous classes?

Anonymous classes are classes that do not have their own type. What am I talking about? When we talked about interfaces, I mentioned that you could not create an instance of an object: you can only create an instance of a class that implements an interface. What if you don't want some class to implement an interface but need an object that implements the interface? And this is likely to be the object's only use. And you don't have any need to create a full-fledged implementation class. How would you do it? That's right! By using an anonymous class! Exploring questions and answers from a job interview for a Java developer position. Part 5 - 4Suppose we have some Animal interface:

public final interface Animal {
   public void speak();
}
If we want to use an anonymous class to instantiate a given interface:

Animal cat = new Animal() {
   @Override
   public void speak() {
       System.out.println("Meow! Meow! Meow!");
   }
};
And then, you can safely use this object and its implemented speak() method. In other words, the anonymous class implements the interface and all its abstract methods, right here and now. Otherwise, we would not be able to create an interface/abstract class object since there would be unimplemented/abstract methods. As I mentioned, anonymous classes are used not only to implement an interface's abstract methods but also to implement the abstract methods of an abstract class. This approach is good for situations when an object is used once or when a given method implementation is needed only once. There is no need to create a separate class that will implement the required abstract class/interface. But I also note that anonymous classes are rarely used in work. As a rule, ordinary classes are still given preference. You can read more about anonymous classes here in this article.

48. What are primitive classes?

I think this is a misleading question, possibly a trick question, since Java has no such thing as primitive classes. There is only the concept of primitive types, which we considered previously. We recall that Java has 8 primitive types: byte, short, int, long, float, double, char, boolean.

49. What is a wrapper class?

The main problem with using primitive types in Java is that they are not classes, and Java is an OOP language. That is, programs written in this language amount to interactions between objects. But primitives are not objects. They do not have methods, even the standard methods of the Object class. But what if we need to use a primitive as a key in a Map? Then we need to call its hashCode() method. You can also call its equals() method there. What then? There are oodles and oodles of moments where you need a class, not a primitive. This makes primitives unusable and undesirable elements in a program because they violate the very idea of OOP. But the situation isn't as bad as it seems. After all, Java has the concept of primitive wrappers. In Java, every primitive type has a twin — a wrapper class.
  • byte -> Byte.class
  • short -> Short.class
  • int -> Integer.class
  • long -> Long.class
  • float -> Float.class
  • double -> Double.class
  • char -> Character.class
  • boolean -> Boolean.class
These types represent the simple types, but in full-fledged classes with a bunch of varied and helpful methods. The concepts of autoboxing and unboxing were introduced to allow these classes to be used conveniently. Autoboxing is the automatic conversion of a primitive type to its analogous class, if necessary (for example, converting int to Integer). Unboxing is the opposite process: automatic conversion of a primitive wrapper class to a primitive type (for example, converting Integer to int). Thanks to the introduction of primitive wrapper classes and the autoboxing and unboxing processes, primitive types are now full-fledged members of Java as an OOP language. Exploring questions and answers from a job interview for a Java developer position. Part 5 - 5For a more in-depth discussion of this topic, I strongly recommend reading this article.

50. What is a nested class? Where is it used?

A nested class is a class that is itself a member of another class. There are 4 kinds of these nested classes in Java: 1. Inner class This kind of class is declared directly in the body of another class. An inner class is a non-static nested class and can access any private field or instance method of the outer class. As an example, let's create a zoo that contains an animal — a zebra:

public class Zoo {
   class Zebra {
       public void eat(String food) {
           System.out.println("Zebra eats " + food);
       }
   }
}
Not complicated, right? Let's take a look at an example of creating an instance of the inner class:

Zoo.Zebra zebra = new Zoo().new Zebra();
zebra.eat("apple");
As you have already seen, it is necessary first to create an object of the enclosing class. Then you use the object reference to create an instance of the inner class. I would also like to point out that an inner class (non-static nested class) cannot have static methods or static fields. This is precisely because the inner class is implicitly associated with an instance of its outer class, and therefore cannot declare any static methods within itself. 2. Static nested classes These classes are similar to the previous category, but they have the static access modifier in the class declaration. Since this kind of class does not have access to the non-static fields of the outer class, it looks more like a static part of the outer class than an inner class. But this class has access to all static members of the outer class, even the private ones. Example of a static nested class:

public class Zoo {
   static class Zebra {
       public void eat(String food) {
           System.out.println("Zebra eats " + food);
       }
   }
}
It is created in a slightly different from the previous one:

Zoo.Zebra zebra = new Zoo.Zebra();
zebra.eat("apple");
Here we don't need an object of the outer class to create an object of the static nested class. We only need to know the nested class's name to find it within the outer class. 3. Local classes Local classes are classes declared inside the body of a method. Objects of a local class can be created and used only within the enclosing method. Example:

public class Zoo {
   public void feed(String animal, String food) {
       switch(animal) {
           case "zebra":
               class Zebra {
                   public void eat(String food) {
                       System.out.println("Zebra eats " + food);
                   }
               }
               Zebra zebra = new Zebra();
               zebra.eat(food);
               ...
Here's an example:

Zoo zoo = new Zoo();
zoo.feed("zebra", "apple");
If you didn't see the code for the feed() method, then you wouldn't even suspect that a local class exists, would you? A local class cannot be static or transient, but it can be marked as abstract or final (one OR the other, but not both, since simultaneously using these two modifiers creates a conflict). 4. Anonymous classes We already talked about anonymous classes above, and as you will remember, they can be created from two sources — interfaces and classes. Reasons to use them Nested static and non-static classes are used because sometimes it is better to embed small classes in more general ones and keep them together so that they have higher cohesion and a common purpose. Basically, nested classes let you increase the encapsulation of your code. You might choose to use a local class if the class is used exclusively within a single method. In this case, do we need to spread the code over the application? No. That said, I will add that in my experience I have never seen anyone use local classes, because whether they are needed or not is highly controversial. You might use anonymous classes when a specific implementation of an interface or an abstract class is needed only once. In that case, there is no need to create a separate, full-fledged class with an implementation. Instead, we kept it simple and implemented the method(s) we need using an anonymous class, used the object, and then forgot about it (of course, the garbage collector didn't forget). Your understanding of nested classes will be enhanced by the article here.

51. What access modifiers can a class have?

There are different types of classes and different access modifiers apply to them:
  • an outer class can have the public access modifier or no modifier at all (the default modifier);
  • an inner class (non-static nested class) can have any one of the 4 access modifiers;
  • a nested static class can have any one of the access modifiers except protected because this modifier implies inheritance, which contradicts any static member of the class (static members are not inherited);
  • a local class can only have the default modifier (i.e. no modifier at all);
  • an anonymous class has no class declaration, so it has no access modifier at all.
This is where we'll end for today. See you soon!Exploring questions and answers from a job interview for a Java developer position. Part 5 - 6Exploring questions and answers from a job interview for a Java developer position. Part 5 - 7
Read more:
Comments (1)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Thomas Level 7, Scottsdale, United States
16 September 2021
Must Read. Tons of great information and different ways to look at JAVA !