1. What is Java?
Java is a high-level, object-oriented programming language developed by Sun Microsystems. It is platform-independent and designed to be portable, secure, and easy to use.
2. Explain the difference between "==" and ".equals()" in Java.
"==" compares object references, while ".equals()" compares the actual content of objects. In most cases, ".equals()" is used for comparing the content of strings and objects.
3. Describe the newly added features in Java 8?
Here are the newly added features of Java 8:
Feature Name | Description |
---|---|
Lambda expression | A function that can be shared or referred to as an object. |
Functional Interfaces | Single abstract method interface. |
Method References | Uses function as a parameter to invoke a method. |
Default method | It provides an implementation of methods within interfaces enabling 'Interface evolution' facilities. |
Stream API | Abstract layer that provides pipeline processing of the data. |
Date Time API | New improved joda-time inspired APIs to overcome the drawbacks in previous versions |
Optional | Wrapper class to check the null values and helps in further processing based on the value. |
Nashorn, JavaScript Engine | An improvised version of JavaScript Engine that enables JavaScript executions in Java, to replace Rhino. |
4. In which programming paradigm Java 8 falls?
- Object-oriented programming language.
- Functional programming language.
- Procedural programming language.
- Logic programming language
5. What are the significant advantages of Java 8?
- Compact, readable, and reusable code.
- Less boilerplate code.
- Parallel operations and execution.
- Can be ported across operating systems.
- High stability.
- Stable environment.
- Adequate support
6. What are functional or SAM interfaces?
Functional Interfaces are an interface with only one abstract method. Due to which it is also known as the Single Abstract Method (SAM) interface. It is known as a functional interface because it wraps a function as an interface or in other words a function is represented by a single abstract method of the interface.
Functional interfaces can have any number of default, static, and overridden methods. For declaring Functional Interfaces @FunctionalInterface annotation is optional to use. If this annotation is used for interfaces with more than one abstract method, it will generate a compiler error.
@FunctionalInterface // Annotation is optional public interface Foo() { // Default Method - Optional can be 0 or more public default String HelloWorld() { return "Hello World"; } // Static Method - Optional can be 0 or more public static String CustomMessage(String msg) { return msg; } // Single Abstract Method public void bar(); } public class FooImplementation implements Foo { // Default Method - Optional to Override@Overridepublic default String HelloWorld() { return "Hello Java 8"; } // Method Override@Overridepublic void bar() {\tSystem.out.println(“Hello World”);} } public static void main(String[] args) { FooImplementation fi = new FooImplementation();System.out.println(fi.HelloWorld());System.out.println(fi.CustomMessage(“Hi”));fi.bar();}
7. Can a functional interface extend/inherit another interface?
A functional interface cannot extend another interface with abstract methods as it will void the rule of one abstract method per functional interface. E.g:
interface Parent { public int parentMethod(); } @FunctionalInterface // This cannot be FunctionalInterface interface Child extends Parent { public int childMethod(); // It will also extend the abstract method of the Parent Interface // Hence it will have more than one abstract method // And will give a compiler error }
It can extend other interfaces which do not have any abstract method and only have the default, static, another class is overridden, and normal methods. For eg:
interface Parent { public void parentMethod(){ System.out.println("Hello"); } } @FunctionalInterface interface Child extends Parent { public int childMethod(); }
8. What is the default method, and why is it required?
A method in the interface that has a predefined body is known as the default method. It uses the keyword default. default methods were introduced in Java 8 to have 'Backward Compatibility in case JDK modifies any interfaces. In case a new abstract method is added to the interface, all classes implementing the interface will break and will have to implement the new method. With default methods, there will not be any impact on the interface implementing classes. default methods can be overridden if needed in the implementation. Also, it does not qualify as synchronized or final.
@FunctionalInterface // Annotation is optional public interface Foo() { // Default Method - Optional can be 0 or more public default String HelloWorld() { return "Hello World"; } // Single Abstract Method public void bar(); }
9. What are static methods in Interfaces?
Static methods, which contains method implementation is owned by the interface and is invoked using the name of the interface, it is suitable for defining the utility methods and cannot be overridden.
10. What are some standard Java pre-defined functional interfaces?
Some of the famous pre-defined functional interfaces from previous Java versions are Runnable, Callable, Comparator, and Comparable. While Java 8 introduces functional interfaces like Supplier, Consumer, Predicate, etc. Please refer to the java.util.function doc for other predefined functional interfaces and its description introduced in Java 8.
Runnable: use to execute the instances of a class over another thread with no arguments and no return value.
Callable: use to execute the instances of a class over another thread with no arguments and it either returns a value or throws an exception.
Comparator: use to sort different objects in a user-defined order
Comparable: use to sort objects in the natural sort order
11. What are the various categories of pre-defined function interfaces?
Function: To transform arguments in returnable value.
Predicate: To perform a test and return a Boolean value.
Consumer: Accept arguments but do not return any values.
Supplier: Do not accept any arguments but return a value.
Operator: Perform a reduction type operation that accepts the same input types.
12. What is the lambda expression in Java and How does a lambda expression relate to a functional interface?
Lambda expression is a type of function without a name. It may or may not have results and parameters. It is known as an anonymous function as it does not have type information by itself. It is executed on-demand. It is beneficial in iterating, filtering, and extracting data from a collection.
As lambda expressions are similar to anonymous functions, they can only be applied to the single abstract method of Functional Interface. It will infer the return type, type, and several arguments from the signature of the abstract method of functional interface.
13. What is the basic structure/syntax of a lambda expression?
FunctionalInterface fi = (String name) -> { System.out.println("Hello "+name); return "Hello "+name; }
Lambda expression can be divided into three distinct parts as below:
1. List of Arguments/Params:
(String name)
A list of params is passed in () round brackets. It can have zero or more params. Declaring the type of parameter is optional and can be inferred for the context.
2. Arrow Token:
->
Arrow token is known as the lambda arrow operator. It is used to separate the parameters from the
body, or it points the list of arguments to the body. 3. Expression/Body:
{ System.out.println("Hello "+name); return "Hello "+name; }
A body can have expressions or statements. {} curly braces are only required when there is more than one line. In one statement, the return type is the same as the return type of the statement. In other cases, the return type is either inferred by the return keyword or void if nothing is returned.
14. What are the features of a lambda expression?
Below are the two significant features of the methods that are defined as the lambda expressions:
- Lambda expressions can be passed as a parameter to another method.
- Lambda expressions can be standalone without belonging to any class.
15. What is a type interface?
Type interface is available even in earlier versions of Java. It is used to infer the type of argument by the compiler at the compile time by looking at method invocation and corresponding declaration.
16. What are the types and common ways to use lambda expressions?
A lambda expression does not have any specific type by itself. A lambda expression receives type once it is assigned to a functional interface. That same lambda expression can be assigned to different functional interface types and can have a different type.
For eg consider expression s -> s.isEmpty() :
Predicate<String> stringPredicate = s -> s.isEmpty();
Predicate<List> listPredicate = s -> s.isEmpty();
Function<String, Boolean> func = s -> s.isEmpty();
Consumer<String> stringConsumer = s -> s.isEmpty();
Common ways to use the expression
Assignment to a functional Interface —>
Predicate<String> stringPredicate = s -> s.isEmpty();
Can be passed as a parameter that has
a functional type —> stream.filter(s -> s.isEmpty())
Returning it from a function —>
return s -> s.isEmpty()
Casting it to a functional type —>
(Predicate<String>) s -> s.isEmpty()
17. In Java 8, what is Method Reference?
Method reference is a compact way of referring to a method of functional interface. It is used to refer to a method
without invoking it. :: (double colon) is used for describing the method reference. The syntax is
class::methodName
For e.g.:
Integer::parseInt(str) \\\\
method reference
str -> Integer.ParseInt(str); \\\\
equivalent lambda
18. What does the String::ValueOf expression mean?
It is a static method reference to method Valueof() of class String. It will return the string representation of the argument passed.
19. What are the advantages of using the Optional class?
Below are the main advantage of using the Optional class:
It encapsulates optional values, i.e., null or not-null values, which helps in avoiding null checks, which results in better, readable, and robust code It acts as a wrapper around the object and returns an object instead of a value, which can be used to avoid run-time NullPointerExceptions.
20. What are the sources of data objects a Stream can process?
A Stream can process the following data:
- A collection of an Array.
- An I/O channel or an input device.
- A reactive source (e.g., comments in social media or tweets/re-tweets)
- A stream generator function or a static factory.
21. What are Intermediate and Terminal operations?
Intermediate Operations:
- Process the stream elements.
- Typically transforms a stream into another stream.
- Are lazy, i.e., not executed till a terminal operation is invoked.
- Does internal iteration of all source elements.
- Any number of operations can be chained in the processing pipeline.
- Operations are applied as per the defined order.
- Intermediate operations are mostly lambda functions.
Terminal Operations:
- Kick-starts the Stream pipeline.
- used to collect the processed Stream data.
int count = Stream.of(1, 2, 3, 4, 5).filter(i -> i <4) // Intermediate Operation filter.count(); // Terminal Operation count
22. What are the most commonly used Intermediate operations?
Filter(Predicate<T>) - Allows selective processing of Stream elements. It returns elements that are satisfying the supplied condition by the predicate.
map(Funtion<T, R>) - Returns a new Stream, transforming each of the elements by applying the supplied mapper function.= sorted() - Sorts the input elements and then passes them to the next stage.
distinct() - Only pass on elements to the next stage, not passed yet.
limit(long maxsize) - Limit the stream size to maxsize.
skip(long start) - Skip the initial elements till the start.
peek(Consumer) - Apply a consumer without modification to the stream.
flatMap(mapper) - Transform each element to a stream of its constituent elements and flatten all the streams into a single stream.
23. What is the stateful intermediate operation? Give some examples of stateful intermediate operations.
To complete some of the intermediate operations, some state is to be maintained, and such intermediate operations are called stateful intermediate operations. Parallel execution of these types of operations is complex.
For Eg: sorted() , distinct() , limit() , skip() etc.
Sending data elements to further steps in the pipeline stops till all the data is sorted for sorted() and stream data elements are stored in temporary data structures.
24. What is the most common type of Terminal operations?
- collect() - Collects single result from all elements of the stream sequence.
-
reduce() - Produces a single result from all elements of the stream sequence
- count() - Returns the number of elements on the stream.
- min() - Returns the min element from the stream.
- max() - Returns the max element from the stream.
-
Search/Query operations
- anyMatch() , noneMatch() , allMatch() , ... - Short-circuiting operations.
- Takes a Predicate as input for the match condition.
- Stream processing will be stopped, as and when the result can be determined.
-
Iterative operations
- forEach() - Useful to do something with each of the Stream elements. It accepts a consumer.
- forEachOrdered() - It is helpful to maintain order in parallel streams.
25. What is the difference between findFirst() and findAny()?
findFirst() | findAny() |
---|---|
Returns the first element in the Stream | Return any element from the Stream |
Deterministic in nature | Non-deterministic in nature |
26. How are Collections different from Stream?
Collections are the source for the Stream. Java 8 collection API is enhanced with the default methods returning Stream<T> from the collections.
Collections | Streams |
---|---|
Data structure holds all the data elements | No data is stored. Have the capacity to process an infinite number of elements on demand |
External Iteration | Internal Iteration |
Can be processed any number of times | Traversed only once |
Elements are easy to access | No direct way of accessing specific elements |
Is a data store | Is an API to process the data |
27. What is the feature of the new Date and Time API in Java 8?
- Immutable classes and Thread-safe
- Timezone support
- Fluent methods for object creation and arithmetic
- Addresses I18N issue for earlier APIs
- Influenced by popular joda-time package
- All packages are based on the ISO-8601 calendar system
28. What are the important packages for the new Data and Time API?
-
java.time
- dates
- times
- Instants
- durations
- time-zones
- periods
- Java.time.format
- Java.time.temporal
- java.time.zone
29. Explain with example, LocalDate, LocalTime, and LocalDateTime APIs.
LocalDate
- Date with no time component
- Default format - yyyy-MM-dd (2020-02-20)
- LocalDate today = LocalDate.now(); // gives today’s date
- LocalDate aDate = LocalDate.of(2011, 12, 30); //(year, month, date)
LocalTime
- Time with no date with nanosecond precision
- Default format - hh:mm:ss:zzz (12:06:03.015) nanosecond is optional
- LocalTime now = LocalTime.now(); // gives time now
- LocalTime aTime2 = LocalTime.of(18, 20, 30); // (hours, min, sec)
LocalDateTime
- Holds both Date and Time
- Default format - yyyy-MM-dd-HH-mm-ss.zzz (2020-02-20T12:06:03.015)
- LocalDateTime timestamp = LocalDateTime.now(); // gives timestamp now
- //(year, month, date, hours, min, sec)
- LocalDateTime dt1 = LocalDateTime.of(2011, 12, 30, 18, 20, 30);
30. Define Nashorn in Java 8
Nashorn is a JavaScript processing engine that is bundled with Java 8. It provides better compliance with ECMA (European Computer Manufacturers Association) normalized JavaScript specifications and better performance at run-time than older versions.
31. Differentiate between Volatile and Transient Variable in Java.
Volatile Variable | Transient Variable |
---|---|
The volatile keyword against the variable indicates that the content of the variable is stored in the main memory and every read of the variable should be done from the main memory and not the CPU cache and every write should be written to the main memory and not just to the CPU cache. | Transient is used when we do not want the variable to be serialised. |
Volatile ensures that the JVM does not re-order the variables and ensures that the synchronization issues are avoided. | Transient provides flexibility and control over the attributes of objects from being serialized. |
Volatile variables do not have any default values. | Transient variables are initialized with default value corresponding to the data type at the time of deserialization. |
Volatile variables can be used along with the static keyword. | Transient variables cant be used along with static keywords because the static variables are class-level variables and not related to the individual instances. This matters during serialization. |
Volatile variables can be used along with the final keyword. | It is not recommended to use final with transient variables as it would cause problems for re-initializing the variables once the values are populated by default at the time of deserialization. |
32. Differentiate between the Vector and ArrayList collections in Java.
ArrayList and Vector collection classes both implement the List interface and are derived from AbstractList. Both
these classes are index-based, meaning objects can be retrieved from the collection based on the index using the
get(index)
method.
Category | Vector | ArrayList |
---|---|---|
Synchronization | Vector is synchronized and thread-safe by default. This means that the internal state of the Vector is not compromised even if multiple threads are operating on it. | ArrayList is neither thread-safe nor synchronized. |
Speed | Since Vector is synchronized, it works relatively slower than ArrayList. | ArrayList is faster than Vector because there is no overhead of maintaining synchronization. |
33. What do you understand by the ... in the below method parameters?
public void someMethod(String... info){ // method body}
The 3 dots feature was started in Java 5 and the feature is known as varargs (variable arguments). This simply means that the method can receive one or more/multiple String arguments as shown below:
someMethod("Java", "Interview");
someMethod("Java", "Interview", "Questions");
someMethod(new String[]{"Java", "Interview", "Questions"});
These received arguments can be used as an array and can be accessed by iterating through loops as shown below:
public void someMethod(String... info){ for(String someInfo : info){ // any operation } // The info can be accessed using index based loops too for( int i = 0; i < info.length; i++){ String s = info[i]; //some operation }}
34. Can you write a code for representing thread-safe singleton patterns in Java?
A thread-safe singleton class is created which helps in object initialization in the presence of multiple threads. It can be done using multiple ways:
- Using Enums: Enums are the simplest means of creating a thread-safe singleton class in Java because the synchronization support is inherently done by Java itself. Enums are by default final and this also helps in preventing multiple initializations at the time of serialization.
public enum ThreadSafeSingleton{ SINGLETON_INSTANCE; public void display(){ System.out.println("Thread-safe singleton Display"); }}// The Singleton class methods can be invoked as belowThreadSafeSingleton.SINGLETON_INSTANCE.show();
- Using Static Field Initialization: Thread-safe singleton can also be created by creating the instance at the time of class loading. This is achieved by making use of static fields as the Classloader guarantees that the instances are initialized during class loading and the instance is not visible until that has been fully created.
public class ThreadSafeSingleton{ private static final ThreadSafeSingleton INSTANCE = new ThreadSafeSingleton(); private ThreadSafeSingleton(){ } public static ThreadSafeSingleton getInstance(){ return INSTANCE; } public void display(){ System.out.println("Thread-safe Singleon"); }}ThreadSafeSingleton.getInstance().display();
But the disadvantage of this way is that the initialization cannot be done lazily and the getInstance() method is called even before any client can call.
-
Using synchronized keyword: We can make use of the synchronized keyword upon the getInstance method
as shown below:
- In this method, we can achieve lazy initialization, and also since we use synchronized keywords, the object initialization is also thread-safe.
- The only problem is that since the whole method is synchronized, the performance is impacted in the presence of multiple threads.
public class ThreadSafeSingleton{ // Creating private instance to make it accessible only by getInstance() method private static ThreadSafeSingleton instance; private ThreadSafeSingleton() { // Making constructor private so that objects cant be initialized outside the class } //synchronized getInstance method synchronized public static ThreadSafeSingleton getInstance(){ if (this.instance == null) { // if instance is null, initialize this.instance = new ThreadSafeSingleton(); } return this.instance; }}
- Double-check locking: Here, we will be using a synchronized block of code within the getInstance method instead of making the whole method synchronized. This ensures that only a handful of threads have to wait only for the first time thereby not impacting the performance.
public class ThreadSafeSingleton { // Creating private instance to make it accessible only by getInstance() method private static ThreadSafeSingleton instance; private ThreadSafeSingleton(){ // Making constructor private so that objects cant be initialized outside the class } public static ThreadSafeSingleton getInstance(){ if (instance == null){ //synchronized block of code synchronized (ThreadSafeSingleton.class){ if(instance==null) { // initialize only if instance is null instance = new ThreadSafeSingleton(); } } } return instance; }}
35. What is the importance of the hashCode() and equals() contract?
Consider the scenario of the HashMap object. We know that the Key of the HashMap uses the hashCode() and equals() methods for finding index or finding the value of a given key by uniquely identify the key-value pair in the map. If these methods are not implemented properly, then there are chances where two keys would produce the same output for these methods resulting in inaccuracy and a wrong key’s value might get updated at the time of updation. Hence, it is very much important to implement the hashCode and the equals method correctly. This can be done properly if we follow the hashCode-equals contract. The contract states that
If two objects are equal, then the hashCode method should produce the same result for both objects.
To ensure this, we have to override the hashCode() method whenever we override the equals() method.
36. How is the classpath variable different from the path variables?
The classpath variables are specific to the Java executables and are used for locating the class files. Whereas, the path variable is a variable present in the operating system and is used for locating the system executables.
37. What is the result of the below code and Why?
public class TestClass {public static void main(String[] args) { someMethod(null);}public static void someMethod(Object o) { System.out.println("Object method Invoked");}public static void someMethod(String s) { System.out.println("String method Invoked");}}
The output of this code is “String method Invoked”. We know that null is a value that can be assigned to any kind of object reference type in Java. It is not an object in Java. Secondly, the Java compiler chooses the method with the most specific parameters in method overloading. this means that since the String class is more specific, the method with String input parameter is called.
38. How would you help a colleague with lesser Java experience who has trouble in serializing a class?
I would first check if the colleague has implemented the java.io.serializable interface. If this is done, I will check if they are trying to serialize only non-static members since the static members cannot be serialized. I would also check if the fields that are not serialized are defined as transient accidentally.
39. What is the best possible way to call the wait() method - by using the if construct or the loop construct?
wait() should be called in loop construct always because whenever a thread gets resources to execute again, it is always better to check the condition before execution. The standard way of wait and notify usage is as shown below:
synchronized (resource) { while (wait condition) resource.wait(); // release the resource lock and reacquire it post wait // operations to perform}
40. Can we use HashMap in a multi-threaded environment?
You can use the HashMap but the probability of working fine depends on the way we use it. For instance, consider the HashMap of configuration properties, if the HashMap initialization was done by using just one thread, and the remaining threads do the task of reading from the map, then HashMap would work perfectly well.
The problem arises when there is at least one thread that updates the Map by means of adding, updating, or deleting the map content. The put() method of the map resizes the map that can cause a deadlock or infinite loop while the threads operate. Hence, during such scenarios, we can use the HashTable or ConcurrentHashMap.
41. What is the result of the below code?
public class InterviewbitProblem{public static void main(String[] arr){ System.out.println(0.1*3 == 0.3); System.out.println(0.1*2 == 0.2);}}
The statements result in:System.out.println(0.1*3 == 0.3);
-> Prints falseSystem.out.println(0.1*2 == 0.2);
-> Prints true
This expectation mismatch is due to the error that occurs while rounding float-point numbers and the fact that in Java, only the floating-point numbers that are powers of 2 are represented accurately by the binary representation. The rest of the numbers should be rounded to accommodate the limited bits as required.
42. What will happen if you run 1.0/0.0?
The double class provides certain rules like Double.INFINITY, NaN, -0.0, etc which aids in arithmetic calculations. The given problem will return Double.INFINITY without throwing any Arithmetic Exception.
43. Is it possible to override a method to throw RuntimeException from throwing NullPointerException in the parent class?
Yes, this is possible. But it is not possible if the parent class has a checked Exception. This is due to the below rule of method overriding in cases of checked exceptions:
The method that wants to override a parent class method can not throw a higher Exception than the overridden method.
This means that if the overridden method is throwing IOException, then the overriding child class method can only throw IOException or its sub-classes. This overriding method can not throw a higher Exception than the original or overridden method.
44. Is there any difference in defining or creating a String by using String literal and by using the new() operator?
Creating string using the new operator ensures that the String is created in the heap alone and not into the string pool. Whereas, creating string using literal ensures that the string is created in the string pool. String pool exists as part of the perm area in the heap. This ensures that the multiple Strings created using literal having same values are pointed to one object and prevents duplicate objects with the same value from being created.
45. What is the output of the below code?
public class InterviewbitProblem{ public static void main(String[] args) { Integer num1 = 1000, num2 = 1000; System.out.println(num1 == num2);//1 Integer num3 = 20, num4 = 20; System.out.println(num3 == num4);//2 }}
Line 1 results in false, whereas line 2 results in true. Let us see why.
In Java, if the references point to
different objects and have the same content, they are not equal in terms of using double equals. By this logic, the
statement num3==num4
should have resulted in false. But, the Integer.java
class in Java has
a private inner class called IntegerCache.java
which helps to cache the Integer objects ranging from
-128 to 127
. All the numbers lying between this range are cached internally by the Integer class. While
defining an object as:
Integer num3 = 20;
Internally, it is converted to Integer by using:
Integer num = Integer.valueOf(20);
The valueOf method from the Integer class is defined like:
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i<=IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i);}
This means that if the value lies in the range -128 to 127, then it returns the Integer instance from the cache, else it creates a new instance. This means that the num3 and num4 point to the same object in the IntegerCache and thereby the comparison results in true.
46. What is the result of the below program?
class X { static int i = 1111; static{ i = i-- - --i; //L1 } { i = i++ + ++i; //L2 }}class Y extends X{ static{ i = --i - i--; //L3 } { i = ++i + i++; //L4 }}public class DriverClass{ public static void main(String[] args){ Y y = new Y(); System.out.println(y.i); //L5 }}
Let us evaluate the expressions one by one:
L1 ->
i = i-- - --i; i = 1111 - 1109 = 2
L2 ->
i = i++ + ++i; i = 0 + 2 = 2
L3 ->
i = --i - i--;i = 1 - 1 = 0
L4 ->
i = ++i + i++;i = 3 + 3 = 6 = y.i
L5 ->
y.i = i from class Y which is 6.
Hence the output is 6.
47. What is the output of the below code and why?
public class InterviewbitTest { private static int counter = 0; void InterviewbitTest() { counter = 20; } InterviewbitTest(int x){ counter = x; } public static void main(String[] args) { InterviewbitTest interviewbitTest = new InterviewbitTest(); System.out.println(counter); }}
The output of the code is “Compile Error” This is because the code is not able to find any constructor that matches InterviewbitTest().
48. Is it necessary to declare all immutable objects as final?
This is not necessary. The functionality of achieving immutability can also be achieved by defining the members of a class as private and not providing any setter methods to modify/update the values. Any references to the members should not be leaked and the only source of initializing the members should be by using the parameterized constructor.
We should note that the variables declared as final only takes care of not re-assigning the variable to a different value. The individual properties of an object can still be changed.
49. What do you know about Factory Design Pattern in Java?
Factory design pattern is the most commonly used pattern in Java. They belong to Creational Patterns because it provides means of creating an object of different instances. Here, the logic of object creation is not exposed to the client. It is implemented by using a standard interface. It gives provision to select object types that we need for creation. This is why, they are also known as Virtual Constructors. For more information regarding the implementation, you can refer here.