编程语言及面向对象基础题
Design Pattern
What is singleton? What’s its cons and pros? How to implement it?Definition
: Singleton pattern is a design pattern that ensure that only one instance of a class is created and Provide a global access point to the object.
When to use
: Singleton pattern should be used when we must ensure that only one instance of a class is created and when the instance must be available through all the code. A special care should be taken in multithreading environments when multible threads must access the same resources throught the same singleton object.
Examples
: Printer spooler, logger, configuration classes
Implementation
:
Lazy Instantiation using double locking mechanism. This make sure the synchronization while reduce cost of locking by check null first.
class Singleton
{
private static Singleton instance;
private Singleton()
{
System.out.println("Singleton(): Initializing Instance");
}
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class)
{
if (instance == null)
{
System.out.println("getInstance(): First time getInstance was invoked!");
instance = new Singleton();
}
}
}
return instance;
}
public void doSomething()
{
System.out.println("doSomething(): Singleton does something!");
}
}
The enum way
public enum Singleton {
INSTANCE;
public void execute (String arg) {
// Perform operation here
}
}
What is (simple) factory pattern? What’s its cons and pros? How to implement it?Definition
: Factory pattern is a design pattern that creates objects without exposing the instantiation logic to the client and refers to the newly created object through a common interface.When to use
: When there’re so many different sub-classes of one abstract class and we want to instantiate one of them, we could use factory to instantiate it without knowing its implementation class.Example
: In Amazon, when we want to schedule a new task we do not new it. We use a task factory and create it by given task name.Implementation
:
public class ProductFactory{
public Product createProduct(String ProductID){
if (id==ID1)
return new OneProduct();
if (id==ID2) return
return new AnotherProduct();
//if the id doesn't have any of the expected values
return null;
}
}
OOP
What’s the difference between interface and abstract class?
Abstract classes can have constants, members, method stubs and defined methods.
Methods and members of an abstract class can be defined with any visibility, whereas all method of an interface must be defined as public.
A child class can only extend a single abstract class, but a class can can implement multiple other intefaces
Usually, we use abstract class
when we need inheritance relation. For example, when I worked in Amazon fulfillment team, we used a payload abstract class and created different specific payload class for different carriers.
For interfaces
, we often use it while creating APIs. For example, we have a service which would be called by other service. Then we will provide a interface for our service so that other teams can use our service without knowing the detail of implementation.
What’re the basic concepts of object oriented programming?
What is polymorphism in OOP?
Polymorphism is the ability (in programming) to present the same interface for differing underlying forms (data types).
The classic example is the Shape
class and all the classes that can inherit from it (square
, circle
, dodecahedron
, irregular polygon
, splat
and so on). With polymorphism, each of these classes will have different underlying data. A point shape needs only two co-ordinates (assuming it’s in a two-dimensional space of course). A circle needs a center and radius. A square or rectangle needs two co-ordinates for the top left and bottom right corners (and possibly) a rotation. An irregular polygon needs a series of lines.
Java
What’s the difference between Java and C++
C++ has pointer and it can manipulate address directly while Java only has reference of object and more memory-safe
Java source code will be converted to byte code via compiler first. The interpreter execute the byte code at run time. C++ run and compile only using compiler which converts source code into machine level language.
Java is platform independent because it relied on a virtual machine. C++ is depends upon operating system and machines.
Java doesn’t support unsigned arithmetic. C++ support native unsigned arithmetic
Java has automatic garbage collection while C++ usually manually manage memory through new and delete
What is static keyword? What is final keyword? What is static final keyword?static
:
static fields are shared among all instances of any class. You can think of them as some kind of global mutable storage. static members belong to the class instead of a specific instance. It means that only one instance of a static field exists
final
:
If you make any variable as final, you cannot change the value of final variable(It will be constant).
If you make any method as final, you cannot override it.
If you make any class as final, you cannot extend it.
final static
:
it has both feature from static and final, so final static field is constant and global
Is null an object?
No, it is not. It is a special type which cannot be used to instantiate a new object.
What’s the difference between an exception and an error?
An Error
is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions.
The class Exception
and its subclasses are a form of Throwable that indicates conditions that a reasonable application might want to catch.
What is Java garbage collection? How does it it work?
Garbage collection is the process of reclaiming the unused memory space and making it available for the future instances.Eden Space
: When an instance is created, it is first stored in the eden space in young generation of heap memory area.Survivor Space (S0 and S1)
: As part of the minor garbage collection cycle, objects that are live (which is still referenced) are moved to survivor space S0 from eden space. Similarly the garbage collector scans S0 and moves the live instances to S1.Instances that are not live (dereferenced) are marked for garbage collection. Depending on the garbage collector (there are four types of garbage collectors available and we will see about them in the next tutorial) chosen either the marked instances will be removed from memory on the go or the eviction process will be done in a separate process.Old Generation
: Old or tenured generation is the second logical part of the heap memory. When the garbage collector does the minor GC cycle, instances that are still live in the S1 survivor space will be promoted to the old generation. Objects that are dereferenced in the S1 space is marked for eviction.Major GC
: Old generation is the last phase in the instance life cycle with respect to the Java garbage collection process. Major GC is the garbage collection process that scans the old generation part of the heap memory. If instances are dereferenced, then they are marked for eviction and if not they just continue to stay in the old generation.Memory Defragmentation
: Once the instances are deleted from the heap memory the location becomes empty and becomes available for future allocation of live instances. These empty spaces will be fragmented across the memory area. For quicker allocation of the instance it should be defragmented. Based on the choice of the garbage collector, the reclaimed memory area will either be compacted on the go or will be done in a separate pass of the GC.
When an object becomes eligible for garbage collection?
Any instances that cannot be reached by a live thread.
Circularly referenced instances that cannot be reached by any other instances
There’re mainly two ways: Reference counting and tracing GC
What is Java virtual machine? How does it work?
When your Java project builds, it translates the source code
(contained in .java source files) to Java bytecode
(most often contained in .class files). When you run a Java application on your computer, cellphone, or any other Java-enabled platform, you essentially pass this Java bytecode to the Java Virtual Machine. The interpreter in the Java Virtual Machine usually starts compiling the entire bytecode at runtime, following the principles of so-called just-in-time compilation. This makes for the typical, albeit often slight delay when opening a Java application, but generally enhances the program performance compared to interpreted compilation.
When you run a Java application on your computer, cellphone, or any other Java-enabled platform, you essentially pass this Java bytecode to the Java Virtual Machine. The interpreter
in the Java Virtual Machine usually starts compiling the entire bytecode at runtime
, following the principles of so-called just-in-time compilation. This makes for the typical, albeit often slight delay when opening a Java application, but generally enhances the program performance compared to interpreted compilation.
Apart from code compatibility
, the Java Virtual Machine comes with other benefits. One of the most important of those is the relative security
of Java programs as a result of the Java Virtual Machine. Security, meaning that a program running in a virtual machine is far less likely to disrupt the user’s operating system, or corrupt data files, if errors occur. One of the main criticisms voiced against the code compatibility and the Java Virtual Machine is due to the many different implementations of the latter.
C++
What is copy constructor? Can it be inherited?
The copy constructor is a constructor which creates an object by initializing it with an object of the same class, which has been created previously. The copy constructor is used to: Initialize one object from another of the same type. Copy an object to pass it as an argument to a function.
classname (const classname &obj) {
// body of constructor
}
Constructors are different from other class methods in that they create new objects, whereas other methods are invoked by existing objects. This is one reason constructors aren’t inherited. Inheritance means a derived object can use a base-class method, but, in the case of constructors, the object doesn’t exist until after the constructor has done its work.
What is virtual function? What is pure virtual function?Virtual function
: A virtual function makes its class a polymorphic base class. Derived classes can override virtual functions. Virtual functions called through base class pointers/references will be resolved at run-time. That is, the dynamic type of the object is used instead of its static type.
Derived d;
Base& rb = d;
// if Base::f() is virtual and Derived overrides it, Derived::f() will be called
rb.f();
Pure virtual function
: A pure virtual function implicitly makes the class it is defined for abstract (unlike in Java where you have a keyword to explicitly declare the class abstract). Abstract classes cannot be instantiated. Derived classes need to override/implement all inherited pure virtual functions. If they do not, they too will become abstract.
Pure Virtual function:
class Base {
// ...
virtual void f() = 0;
// ...
How to compare two doubles in C++?
Inside the equals() function, we have
if (Abs(x – y) <= EPSILON * Max(1.0f, Abs(x), Abs(y)) return true;
If we have different requirement for relative tolerance and absolute tolerance, then
if (Abs(x - y) <= Max(absTol, relTol * Max(Abs(x), Abs(y)))) return true;
What is memory leak in C++?
A memory leak is a problem in computer programming where free memory that can be used for dynamic allocation is slowly lost to use. Depending upon the leak rate and the program duration of use this can be a mild or serious problem. The problem is severely exacerbated for computer that multitask, that are control or supervisory programs that run for very long times (some run 24/7 for years), or have very limited memory.
A leak can be caused by faulty dynamic memory allocation where a block of memory is temporarily allocated but the programmer forgot to release it
after completing the task that uses it. Or by a runaway stack
being called too many times. Or by a stack push that the programmer forgot to pop
, eating up the stack.
i++ and ++i which is more efficient?
In old compiler, ++i
is more efficient because i++
need to keep a copy of variable before adding. However, in modern compiler, it will be optimized so there will be no difference.
What is the difference between passing by value passing by reference and passing by pointer
f(Type Name)
Passing by value, where Type is int and Name is p (note that int p actually means int* p). In this case, inside your function Name is a copy of the object that you pass to the function.
f(Type & Name)
Passing by reference does not make a copy, but creates an alias to the object instead, so that you can modify the original object.
There are only two ways to pass argument, and passing by pointer is not one of them. You can pass a pointer by its value or its reference. A pointer can receive a NULL parameter, a reference parameter can not. If there’s ever a chance that you could want to pass “no object”, then use a pointer instead of a reference.
For example, If I tell you the URL, I’m passing by reference. You can use that URL to see the same web page I can see. If that page is changed, we both see the changes. If you delete the URL, all you’re doing is destroying your reference to that page – you’re not deleting the actual page itself.
If I print out the page and give you the printout, I’m passing by value. Your page is a disconnected copy of the original. You won’t see any subsequent changes, and any changes that you make (e.g. scribbling on your printout) will not show up on the original page. If you destroy the printout, you have actually destroyed your copy of the object – but the original web page remains intact.
Data Structure
What is hash table? How to implement it? How to avoid collision? How to insert and delete? What’s the runtime?Definition
: It is a structure that can map keys to values. A hash table uses a hash function to compute an index into an array of buckets or slots, from which the desired value can be found.
Collision
:Ideally, the hash function will assign each key to a unique bucket, but it is possible that two keys will generate an identical hash causing both keys to point to the same bucket. Instead, most hash table designs assume that hash collisions—different keys that are assigned by the hash function to the same bucket—will occur and must be accommodated in some way.
Seperate chaining
In the method known as separate chaining, each bucket is independent, and has some sort of list of entries with the same index.Open addressing
When a new entry has to be inserted, the buckets are examined, starting with the hashed-to slot and proceeding in some probe sequence, until an unoccupied slot is found.Linear probing
The interval between probes is fixedQuadratic probing
The interval between probes is increased by adding the successive outputs of a quadratic polynomial to the starting value given by the original hash computataionDouble hasing
The interval between probes is computed by another hash function
Load factor
: The number of entries divided by the number of buckets. n is number of entries, k is number of buckets. Usually the load factor is 0.75 to make a good trade off between time and space.
$$ f=\frac{n}{k} $$
Dynamic resizing
: To keep the load factor under a certain limit, e.g., under 3/4, many table implementations expand the table when items are inserted. Resizing is accompanied by a full or incremental table rehash whereby existing items are mapped to new bucket locations.
Deletion
:
Separate chaining (overflow with linked list): just delete the target in linked list
Open addressing (linear probe): deletions are done by marking an element as deleted, rather than erasing it entirely. Deleted locations are treated as empty when inserting and as occupied during a search.
Perfomance analysis
:
O(1) average and amortized
O(N) in worst case that every insertion have collision
What is the difference between an arraylist and linkedlist?
It is better to be explained with an example, like in which case we should use which data structure
Searching in ArrayList takes O(1) time while searching in LinkedList takes O(N) time
Deletion in ArrayList takes O(N) time while deletion in LinkedList takes O(1) time
Insertion in ArrayList takes O(N) time while insertion in LinkedList takes O(1) time
Memory overhead: ArrayList may has redundancy while LinkedList need more space to put pointers
Other
How to swap two number without using temporary variable?
Two ways: One is by XOR
a ^= b;
b ^= a;
a ^= b;
The other is by add and subtract
a = a + b;
b = a - b;
a = a - b;
How to add two integer without using + – * /?
In digital logic circuits, adding is implemented by XOR gate and AND gate. We could do same thing here. From lowest bit to highest bit, assume a and b are current bit. Value and Carry is similar in arithmetic.
Value = (a XOR b) AND last_Carry
new_Carry = a AND b