TOP QUESTIONS Flashcards

1
Q

Why Interfaces should be preferred over abstract classes?
Effective Java (20)

A

[1] Existing classes can easily be retrofitted to implement a new interface.

All you have to do is to add the required methods, if they don’t yet exist, and to add an
implements clause to the class declaration. For example, many existing classes
were retrofitted to implement the Comparable, Iterable, and Autocloseable
interfaces when they were added to the platform. Existing classes cannot, in
general, be retrofitted to extend a new abstract class. If you want to have two
classes extend the same abstract class, you have to place it high up in the type
hierarchy where it is an ancestor of both classes. Unfortunately, this can cause
great collateral damage to the type hierarchy, forcing all descendants of the new
abstract class to subclass it, whether or not it is appropriate.

[2] Interfaces are ideal for defining mixins.

Loosely speaking, a mixin is a type that a class can implement in addition to its “primary type,” to declare that it pro-vides some optional behavior. For example, Comparable is a mixin interface that allows a class to declare that its instances are ordered with respect to other mutu-ally comparable objects. Such an interface is called a mixin because it allows the
optional functionality to be “mixed in” to the type’s primary functionality.
Abstract classes can’t be used to define mixins for the same reason that they can’t
be retrofitted onto existing classes: a class cannot have more than one parent, and
there is no reasonable place in the class hierarchy to insert a mixin.

[3] Interfaces allow for the construction of nonhierarchical type frameworks.
Type hierarchies are great for organizing some things, but other things don’t fall

neatly into a rigid hierarchy. For example, suppose we have an interface represent-
ing a singer and another representing a songwriter:

public interface Singer {
AudioClip sing(Song s);
}

100 CHAPTER 4 CLASSES AND INTERFACES
public interface Songwriter {
Song compose(int chartPosition);
}
In real life, some singers are also songwriters. Because we used interfaces
rather than abstract classes to define these types, it is perfectly permissible for a
single class to implement both Singer and Songwriter. In fact, we can define a
third interface that extends both Singer and Songwriter and adds new methods
that are appropriate to the combination:
public interface SingerSongwriter extends Singer, Songwriter {
AudioClip strum();
void actSensitive();
}
You don’t always need this level of flexibility, but when you do, interfaces are
a lifesaver. The alternative is a bloated class hierarchy containing a separate class
for every supported combination of attributes. If there are n attributes in the type
system, there are 2n

possible combinations that you might have to support. This is
what’s known as a combinatorial explosion. Bloated class hierarchies can lead to
bloated classes with many methods that differ only in the type of their arguments
because there are no types in the class hierarchy to capture common behaviors.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Why we should favor composition over inheritance?

A

Inheritance violates encapsulation

In other words, a subclass depends on the implementation details of its superclass
for its proper function. The superclass’s implementation may change from release
to release, and if it does, the subclass may break, even though its code has not
been touched. As a consequence, a subclass must evolve in tandem with its
superclass, unless the superclass’s authors have designed and documented it
specifically for the purpose of being extended.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

[1] Tell me about the Single Responsibility principle.
[2] How does this principle help us create better software?
[3] What is the problem with this principle?
[4] How to determine what is a responsibility of given class?

https://www.baeldung.com/java-single-responsibility-principle
https://objectscriptquality.com/docs/metrics/lack-cohesion-methods-lcom4
https://www.aivosto.com/project/help/pm-oo-cohesion.html

A

[1] The Single Responsibility principle is one out of five principles, widely known as SOLID.
The Single Responsibility says that a class should have only one responsibility. Quite often we say that class should have one reason to change.

[2] This principle helps us create better software because of:
a) Testing - a class with single responsibility will have far fewer test cases
b) Lower coupling - fewer functionalities ins a single class will have fewer dependencies
c) Easier to maintain and less error-prone

[3] The problem is that very developer has their vision of the class purpose, which makes things tricky. Since we don’t have strict instructions on how to implement this principle, we are left with our interpretations of what the responsibility will be.
What this means is that sometimes only we, as designers of our application, can decide if something is in the scope of a class or not.
When writing a class according to the SRP principle, we have to think about the problem domain, business needs, and application architecture. It is very subjective, which makes implementing this principle harder then it seems. It will not be as simple as the example we have in this tutorial.

[4]
a) When designing software based on the SRP principle, cohesion is essential, since it helps us to find single responsibilities for our classes. High Cohesion is a desirable state. This concept also helps us find classes that have more than one responsibility.
Classes having multiple responsibilities means multiple reasons to change that class, it means low cohesion which is an undesirable state in software engineering practices.

One of the tools that can help achieve high cohesion in methods is LCOM (Lack of cohesion of methods (sometimes abbreviated LCOM, Brak spójności metod)) . Essentially, LCOM measures the connection between class components and their relation to one another.

b) Things that need to change together should exist together.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

[1] Tell me about Open/Close principle
[2] How to achieve this principle

https://www.baeldung.com/java-open-closed-principle

A

[1] Classes should be open for extension but closed for modification. In doing so, we stop ourselves from modifying existing code and causing potential new bugs in an otherwise happy application.
What this effectively means is that a class should be written in a manner that there should not be any need to modify it. However, it should allow for changes through inheritance or composition.

[2] You can achieve this principle
a) Program by Interface, not by Implementation

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

[1] Tell me about Liskov Substitution principle

https://www.baeldung.com/java-liskov-substitution-principle

A

It extends the Open/Closed principle and enables you to replace objects of a parent class with objects of a subclass without breaking the application. This requires all subclasses to behave in the same way as the parent class. To achieve that, your subclasses need to follow these rules:

Don’t implement any stricter validation rules on input parameters than implemented by the parent class.
Apply at least the same rules to all output parameters as applied by the parent class.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

[1] Tell me about “Interface Segregation Principle” (ZASADA SEGREGACJI INTERFEJSÓW)

https://www.baeldung.com/java-interface-segregation

A

“Clients should not be forced to depend upon interfaces that they do not use“.
In other words, do not force any client to implement an interface that is irrelevant to them.

The goal of this principle is to reduce the side effects of using larger interfaces by breaking application interfaces into smaller ones. It’s similar to the Single Responsibility Principle, where each class or interface serves a single purpose.

Precise application design and correct abstraction is the key behind the Interface Segregation Principle. Though it’ll take more time and effort in the design phase of an application and might increase the code complexity, in the end, we get a flexible code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

[1] Tell me about “Dependency Inversion” principle

https://www.baeldung.com/java-interface-segregation

A

The Dependency Inversion Principle (DIP, zasada odwróconej zależności) states that we should depend on abstractions (interfaces and abstract classes) instead of concrete implementations (classes). The abstractions should not depend on details; instead, the details should depend on abstractions.
OR in another words:
a) High-level modules should not depend on low-level modules. Both should depend on abstractions.
b) Abstractions should not depend on details. Details should depend on abstractions.
So, it’s clear that at the core, the DIP is about inverting the classic dependency between high-level and low-level components by abstracting away the interaction between them.

Consider the example below. We have a Car class that depends on the concrete Engine class; therefore, it is not obeying DIP

public class Car {
private Engine engine;
public Car(Engine e) {
engine = e;
}
public void start() {
engine.start();
}
}
public class Engine {
public void start() {…}
}

The code will work, for now, but what if we wanted to add another engine type, let’s say a diesel engine? This will require refactoring the Car class.
However, we can solve this by introducing a layer of abstraction. Instead of Car depending directly on Engine, let’s add an interface

public interface Engine {
public void start();
}

Now we can connect any type of Engine that implements the Engine interface to the Car class:
public class Car {
private Engine engine;
public Car(Engine e) {
engine = e;
}
public void start() {
engine.start();
}
}
public class PetrolEngine implements Engine {
public void start() {…}
}
public class DieselEngine implements Engine {
public void start() {…}
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Co to jest TDD?

A

Test-driven development (TDD) – technika tworzenia oprogramowania.

Polega na wielokrotnym powtarzaniu kilku kroków:
1) Najpierw programista pisze automatyczny test sprawdzający dodawaną funkcjonalność. Test w tym momencie nie powinien się udać.
2) Później następuje implementacja funkcjonalności. W tym momencie wcześniej napisany test powinien się udać.
3) W ostatnim kroku programista dokonuje refaktoryzacji napisanego kodu, żeby spełniał on oczekiwane standardy.

FAZY TDD:
1)Red - piszemy test, któr kończy się błędem
2)Green - poprawiamy logike, test przechodzi
3) Refactor - piszemy

Jedną z zalet Test-Driven Development jest to, że modyfikując lub dodając funkcjonalność, automatycznie otrzymujemy raporty o wszystkich powiązanych obszarach, popsutych przez nasze zmiany

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

[1] What is a general contract of hashMethod?
[2] What is hashing?
[3] What is the purpose of the hashCode() method?

A

[1]
a) Whenever it is invoked on the same object more than once during an execution of a Java application, hashCode() must consistently return the same value, provided no information used in equals comparisons on the object is modified. This value doesn’t need to stay consistent from one execution of an application to another execution of the same application.

b)f two objects are equal according to the equals(Object) method, calling the hashCode() method on each of the two objects must produce the same value.

c) If two objects are unequal according to the equals(java.lang.Object) method, calling the hashCode method on each of the two objects doesn’t need to produce distinct integer results. However, developers should be aware that producing distinct integer results for unequal objects improves the performance of hash tables.

[2] What is hashing?
Hashing is the process of transforming any given key or a string of characters into another value. This is usually represented by a shorter, fixed-length value or key that represents and makes it easier to find or employ the original string.

[3] Hashing uses functions or algorithms to map object data to a representative integer value. A hash can then be used to narrow down searches when locating these items on that object data map.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

[1] Jaka jest różnica pomiędzy SOAP a REST?
[2] Jakie są różnice?
[3] Kiedy użyć którego sposobu integracji?

A

[1]
SOAP - Simple Object Transfer Procol. Jest to protokół komunikacyjny, który powstał na potrzeby integracji/komunikacji różnych aplikacji. Do wymiany danych używany jest XML.Dosyć stary protokół ale wykorzystywany nadal do dziś ze względu na swoją standaryzacje, bezpieczeństwo.

REST - Representational State Transfer - jest to styl architektoniczny i wzorzec narzucający dobry praktyki wymiany danych za pomocą protokołu HTTP. Stanowi też element standaryzacji protokołu HTTP. W przeciwieństwie do SOAP, REST nie jest protokołem. Jest bezstanowy i cachowany.

[2] RÓŻNICE
a) Dane w REST moga być wymieniane w formacie JSON, XML, YAM, HTML lub jako zwykły tekst. W przypadku SOAP jest tylko możliwy format XML.
b) REST jest bardziej wydajny bo wiadomości w REST np w formacie JSON są mniejsze i tym samym jest mniejszy narzut na wykorzystaną pamięć i szybkość. Ponadto w przeciwieństwie do wywołań REST, wywołań SOAP nie można cachować.
c) Pod względem bezpieczeństwa SOAP jest podobno bardziej bezpieczny niż REST.
d) Rozmiar danych. Wiamosoci w formacie JSON sa mniejsze niż w przypadku SOAPM XML
e) Praca z danymi. W Przypadku SOAP elementu usługi definiowane sa w pliku WSDL oraz XSD. W przypadku REST dostajemy adres usługi pod którym dany zasób i operacja na nim jest dostępna i w celu integracji musimy posłuzyć się dokumentacją.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

[1] Describe Adapter pattern and tell when to use it.
[2] Give real examples when you use it?
[3] How this design pattern help writes better code?

https://refactoring.guru/design-patterns/adapter

A

[1] The adapter is a structural design pattern that allows objects with incompatible interfaces to collaborate.

An adapter is a special object that converts the interface of one object so that another object can understand it.
An adapter wraps one of the objects to hide the complexity of conversion happening behind the scenes. The wrapped object isn’t even aware of the adapter.

[2] When to use the Adapter pattern?
Use the Adapter class when you want to use some existing class, but its interface isn’t compatible with the rest of your code.

[3] How does this pattern help write better code?
We have a separate class between the client and 3rd party class with an incompatible interface. The conversion takes place in the adapter class instead of the code class. Thanks to that we do not break the Single Responsibility principle and the Open/Close principle.

The Adapter pattern lets you create a middle-layer class that serves as a translator between your code and a legacy class, a 3rd-party class, or any other class with a weird interface.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

[1] Describe strategy pattern
[2] When to use the strategy pattern

https://refactoring.guru/design-patterns/strategy

A

[1] Strategy is a behavioral design pattern that lets you define a family of algorithms, put each of them into a separate class, and make their objects interchangeable

The original class, called context, must have a field for storing a reference to one of the strategies. The context delegates the work to a linked strategy object instead of executing it on its own.

[2] When to use
Use the Strategy pattern when you want to use different variants of an algorithm within an object and be able to switch from one algorithm to another during runtime.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

[1] Describe Factory method pattern
[2] When to use this pattern

A

[1] Factory method allows delegation of creation object that share common interface to separate class. Thanks to that we can create objects without impacting client code so that we can avoid breaking rules like Single responsibility and Open/CLose

[2] Use the Factory Method when you don’t know beforehand the exact types and dependencies of the objects your code should work with.

The Factory Method separates product construction code from the code that actually uses the product. Therefore it’s easier to extend the product construction code independently from the rest of the code.

For example, to add a new product type to the app, you’ll only need to create a new creator subclass and override the factory method in it.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

[1] Describe the Template method pattern
[2] When to use the Template method pattern

https://refactoring.guru/design-patterns/template-method

A

[1] Template Method is a behavioral design pattern that defines the skeleton of an algorithm in the superclass but lets subclasses override specific steps of the algorithm without changing its structure.

[2] Use the Template Method pattern when you want to let clients extend only particular steps of an algorithm, but not the whole algorithm or its structure.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

[1] Describe the Facade pattern
[2] When to use the Facade pattern
[3] Pros and cons

https://refactoring.guru/design-patterns/facade

A

[1] Facade is a structural design pattern that provides a simplified interface to a library, a framework, or any other complex set of classes.

[2] Use the Facade pattern when you need to have a limited but straightforward interface to a complex subsystem.

[3] Pros and cons
PROS:
a) You can isolate your code from the complexity of a subsystem
CONS:
a) A facade can become a god object coupled to all classes of an app.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Are parameters passed to method by value or by reference in java?

A

The fundamental concepts in any programming language are “values” and “references”. In Java, Primitive variables store the actual values, whereas Non-Primitives store the reference variables which point to the addresses of the objects they’re referring to.

Both values and references are stored in the stack memory.In case of primitives, the value is simply copied inside stack memory which is then passed to the callee method; in case of non-primitives, a reference in stack memory points to the actual data which resides in the heap. When we pass an object, the reference in stack memory is copied and the new reference is passed to the method.

16
Q

Difference between String, String Builder, and String Buffer.

A

a) String
String variables (literals) are stored in a “constant string pool”. Once the string reference changes the old value that exists in the “constant string pool”, it cannot be erased.

b) StringBuffer and StringBuilder are mutable classes. String is immutable.

c) StringBuffer operations are thread-safe and synchronized whereas StringBuilder operations are not thread-safe. So in a multi-threaded environment, we should use StringBuffer but in the single-threaded environment, we should use StringBuilder. StringBuilder’s performance is faster than StringBuffer’s because of no overhead of synchronization.

17
Q

What is a String pool?

A

String Pool in java is a pool of Strings stored in Java Heap Memory. Because strings are immutable in Java, the JVM can optimize the amount of memory allocated for them by storing only one copy of each literal String in the pool.

18
Q

List all interfaces in java Collection framework and describe them

A

Following are the collection interfaces in java.util which are implemented by various classes. The core collection interfaces are the foundation of the Java Collections Framework.

a) Set - A Set is a Collection that cannot contain duplicate elements. It models the mathematical set abstraction.

b) List - A List is an ordered Collection (sometimes called a sequence). Lists may contain duplicate elements.

c) Queue - Queues typically, but do not necessarily, order elements in a FIFO (first-in-first-out) manner. Among the exceptions are priority queues, which order elements according to a supplied comparator. Whatever the ordering used, elements of the queue are always removed from the head of the queue.

d) Dequeue - The name deque is short for “double ended queue” and is usually pronounced “deck”. This interface defines methods to access the elements at both ends of the deque. A deque can be used both as a LIFO and FIFO structure.

e) Map - An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value. It replaces the abstract class Dictionary (now obsolete) which was part of the legacy collections.