• Tidak ada hasil yang ditemukan

Advanced java Preparing you for java mastery

N/A
N/A
SAMIUL BASIR

Academic year: 2023

Membagikan "Advanced java Preparing you for java mastery"

Copied!
124
0
0

Teks penuh

Andriy has extensive experience in the development of distributed (multi-level) software systems, multi-threaded applications, desktop applications, service-oriented architecture and rich Internet applications. As a professional, he is always open to continuous learning and self-improvement to be more productive in the work he is really passionate about.

Introduction

Instance Construction

  • Implicit (Generated) Constructor
  • Constructors without Arguments
  • Constructors with Arguments
  • Initialization Blocks
  • Construction guarantee
  • Visibility
  • Garbage collection
  • Finalizers

A given class can have multiple initialization blocks and they will all be called in the order they are defined in the code. This is because Java uses garbage collection to manage the lifecycle of objects, and it is the responsibility of the garbage collector to destroy unneeded objects and reclaim memory.

Table 1.1: datasheet
Table 1.1: datasheet

Static initialization

Construction Patterns

  • Singleton
  • Utility/Helper Class
  • Factory
  • Dependency Injection

Basically, its main idea is to ensure that only one instance of a class can be created at any given time. One way to properly format a single element (but in a non-lazy way) is to use a static final property of a class.

Download the Source Code

What’s next

We will discuss this method in part 9 of the tutorial, Concurrency Best Practices. Causes the current thread to wait until another thread calls thenotify() method or thenotifyAll() method for this object.

Table 2.1: datasheet
Table 2.1: datasheet

Methods equals and hashCode

It will guarantee that the behavior of these methods will not be affected by scope changes (however, in real-world projects . it is not always possible). It will guarantee consistent behavior of both methods in case of any changes affecting the fields in question.

Method toString

Method clone

Method equals and == operator

Useful helper classes

Download the Source Code

What’s next

Introduction

Interfaces

First of all, although not explicitly stated, every declaration in the interface is public (and can only be public, for more details on visibility and accessibility rules, please see the Visibility section). And finally, the nested classes, interfaces, or enumerations, in addition to being public, are implicitly declared astatic.

Marker Interfaces

In this more complex case, there are some restrictions implicitly imposed by interfaces on nested constructs and method declarations, and the Java compiler enforces these.

Functional interfaces, default and static methods

This interface marks the class as available for serialization and deserialization, and again it does not specify how this could or should be done. Additionally, the @FunctionalInterface annotation (annotations are covered in detail in Part 5 of the tutorial, How and When to Use Enumerations and Annotations) gives the compiler a hint to verify that the interface contains only one abstract method, so that any changes made in the will be introduced into the interface in the future. do not break this assumption.

Abstract classes

Immutable classes

With arrays, the only way to ensure true immutability is to provide a copy instead of returning the reference to the array. There are some excellent Java source code analyzers (FindBugs) and PMD) that can help a lot by inspecting your code and pointing out common Java programming flaws.

Anonymous classes

Second, follow the correct initialization: if the field is the reference to a collection or an array, don't assign those fields directly from constructor arguments, make the copies instead. It will guarantee that the state of the collection or array will not be changed from outside.

Visibility

Inheritance

However, there are some easy rules that can go a long way in keeping your class hierarchies concise. However, there is no special syntax or keyword to mark the method as overridden, which can cause a lot of confusion.

Multiple inheritance

The well-known "Diamond of Death" problem is often cited as the fundamental flaw of multiple inheritance implementations, so developers are urged to design class hierarchies very carefully. Unfortunately, Java 8 interfaces with default methods are also falling victim to these flaws.

Inheritance and composition

But we can say that Vehicclass is also an engine and could be designed as such using inheritance. IS-A is an inheritance relationship: the subclass also satisfies the specification of the parent class and such an IS-variation of the parent class.

Encapsulation

Consequently, IMA-A is a composition relationship: a class owns (or IMA-A) the objects that belong to it. However, heritage has its place, solves real design issues in a different way, and should not be neglected.

Final classes and methods

Download the Source Code

What’s next

In this section, we will cover the use of generics everywhere, starting from interfaces, classes and methods. However, with a lot of benefits, generics introduce some limitations and side effects, which we will also cover.

Generics and interfaces

It's a very powerful concept (that was discussed a while ago) that allows you to develop abstract algorithms and data structures and provide concrete types that you can work with later. It's very easy to declare and use generic interfaces, but we'll come back to it when we discuss bounded types (wildcards and bounded types) and generic constraints (Constraint on Generic Interfaces).

Generics and classes

Generics and methods

If methods are declared (or defined) as part of generic interface or class, they may (or may not) use the generic types of their owner. They can define their own generic types or mix them with those from their class or interface declaration.

Limitation of generics

Another disadvantage caused by erasing types arises from the fact that it is not possible to use the type parameters of generics in a meaningful way, for example to create new instances of the type, or to change the concrete class of get the type parameter or use it in the instanceof operator. And finally, it is also not possible to create the array instances using the type parameters of generics.

Generics, wildcards and bounded types

If the type parameter is not of interest to the generic class, interface, or method, it can be replaced by . The method store doesn't care what type parameters it's called with, all it needs is to ensure that each type implements the Serializable Interface.

Generics and type inference

Unlike textends, the superkeyword restricts the type parameter to a superclass of another class. Fortunately, the Java 8 release brings more improvements to the compiler and especially to the type inference for generics, so that the code snippet shown above can be compiled successfully, helping the developers to avoid unnecessary typing.

Generics and annotations

The Java 7 release addressed this problem somewhat by making changes in the compiler and introducing the new diamond operator <>. The compiler is able to infer the generic type parameters from the left side and omit them in the right side of the expression.

Accessing generic type parameters

It was a significant step towards making generic syntax less verbose, but the compiler's ability to infer generic type parameters was quite limited. Another interesting use case that often comes up when working with generics in Java is to determine the concrete class of the type with which the generic instance has been parameterized.

When to use generics

This can blow the amount of arguments required by the methods, but with careful design it's not as bad as it seems at first glance. The class itself must be modified to use the intermediate interface // instead of direct implementations.

Download the Source Code

Very clear and concise piece of code, no intermediate interface or other tricks required. In the following parts of the tutorial, generic techniques will often be used to demonstrate other features of the Java language.

What’s next

In this part of the tutorial, we'll cover two more great features introduced to the language as part of the Java 5 release, along with generic articles: enumerations (or enumerations) and annotations. On the other hand, annotations are a special kind of metadata that can be associated with various elements and constructs of the Java language.

Enums as special classes

For example, days of the week are a great example of enums: they are limited to Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, and Sunday. However, the distinguishing part is that every single value is an instance of the enum class in which it is being declared (in our example, DaysOfTheWeek).

Enums and instance fields

From a logical point of view, the day argument should have one of the values ​​declared in the DaysOfTheWeekConstants class. Please note that using the uppercase naming scheme in enums is only a convention, nothing prevents you from not doing so.

Enums and interfaces

The way we implemented the interface is a bit verbose, but it's definitely possible to make it better by combining instance fields and interfaces together. By supporting instance fields and interfaces, enums can be used in a more object-oriented way, bringing some abstraction to rely on.

Enums and generics

Convenient Enums methods

String name() Returns the name of this enum constant, exactly as declared in its enum declaration. Because of the presence of these methods and the hard work of the compiler, there is one more benefit to using enums in your code: they can be used in switching/casting.

Specialized Collections: EnumSet and EnumMap

TheEnumMapis very close to the regular map, with the difference that its keys can be the enum constants of the enum type in question. Note that, like most collection implementations, EnumSetandEnumMapare not thread-safe and cannot be used as they are in a multithreaded environment (we'll discuss thread safety and synchronization in part 9 of the tutorial, Concurrency Best Practices).

When to use enums

Annotations as special interfaces

Second, it's not possible to create an instance of the annotation programmatically using the thenoperator (we'll take a look at some workarounds for that in part 11 of the tutorial, Supporting Reflection and Dynamic Languages). And third, annotations can only declare attributes of primitive types, StringorClass< ?>types and their sets.

Annotations and retention policy

Annotations and element types

In addition to the elements described above, Java 8 introduces two new element types to which annotations can be applied. Unlike the retention policy, an annotation can declare multiple element types to which it can be associated, using the @Target annotation.

Annotations and inheritance

For the most part, any annotations you create should have both a retention policy and element types defined in order to be useful.

Repeatable annotations

Annotation processors

Annotations and configuration over convention

When to use annotations

Download the Source Code

What’s next

In this section of the tutorial, we are going to spend some time discussing different aspects related to designing and implementing methods in Java. As we have seen in previous parts of the tutorial, it is very easy to write methods in Java, but there are many things that can make your methods more readable and efficient.

Method signatures

Internally, the Java compiler converts varargs to an array of the respective type, and this is how varargs can be accessed by the method implementation. The next example shows the use of the checked exceptions as part of the method signature.

Method body

However, because the argument type is unknown, the Java compiler wants to ensure that the varargs are used responsibly and recommends which method should be final and annotated with the @SafeVarargs annotation (more details on annotations can be found in part 5 of the tutorial, How and when to use lists and annotations). Finally, it is generally recommended (but rarely used) to mark the method arguments as final.

Method overloading

In recent years, the checked exceptions have proven to not be as useful as they were intended, resulting in more boilerplate code being written than problems being solved. Although this code snippet can be written without using generics, it is not important for our demonstration purposes.

Method overriding

Nevertheless, combining both generics and overloading can be very powerful, but often not possible in Java, due to type clearing (for more details, please refer to part 4 of the tutorial, How and When to Use Generics). Again, there is only a subtle difference in the method signature (Doublein instead ofNumber), but in this case it is an overloaded version of the method and does not overwrite the parent version.

Inlining

That's when the help of the Java compiler and @Overrideannotations pays off: annotating the method from the last example with @Override increases the compiler error.

Recursion

Method References

Reference to an instance method of a given object someInstance::instanceMethodName Reference to an instance method of any object of a. The last line of the main method uses the reference to printlnmethod to print each element from the string collection to the console and is taken as an argument passed to another method, forEach.

Immutability

Method Documentation

Let's look at a quick example of how methods can be passed as arguments to other methods. Just by looking at the image above, any Java developer from junior to senior level can understand the purpose of the method and the right way to use it.

Figure 6.1: 6.Javadoc.Eclipse
Figure 6.1: 6.Javadoc.Eclipse

Method Parameters and Return Values

Methods as API entry points

Whenever it makes sense, try to design immutable methods (that don't affect the internal state, section Immutability).

Download the Source Code

What’s next

In this part of the tutorial, we will continue to discuss the general principles of good programming style and robust design in Java. We've already seen some of these principles in previous parts of the tutorial, but along the way there will be many new practical tips aimed at improving your skills as a Java developer.

Variable scopes

Class fields and local variables

The calculateValue method introduces a local variable with name value and in doing so hides the class member with the same name. Line08 should have summed the class member and the local variable, but instead it does something very different.

Method arguments and local variables

Boxing and unboxing

Interfaces

However, because the switch is driven by the interface, it is very easy to introduce another implementation using, for example, database or even flat file. Many excellent examples of appropriate use of the interfaces are encapsulated in the Java standard assembly library.

Strings

This implementation can be used anywhere the Timezone service interface is required, isolating the test scenario from dependencies on external components. Although using StringBuilder/StringBuffer is the recommended way to manipulate strings, it can look too murderous in a simple scenario of concatenating two or three strings, so the regular + operator can be used instead, for example: .

Naming conventions

Standard Libraries

Immutability

Testing

Download the Source Code

What’s next

Introduction

Exceptions and when to use them

Checked and unchecked exceptions

Checked exceptions therefore represent invalid conditions in the areas outside the immediate control of the program (such as memory, network, file system, etc. Unlike the unchecked exceptions, checked exceptions must either be caught by the caller or be listed as part of of the method signature (usingthrows keyword).

Using try-with-resources

Fortunately, as of Java 7, there is a new construct introduced into the language called try-with-resources which greatly simplified the overall management of resources. The only thing required for the resource to be used in thetry-with-resources blocks is to implement the AutoCloseable interface.

Exceptions and lambdas

Behind the scenes, the Java compiler expands this construct into something more complex, but to developers the code looks very readable and concise. Many functional interfaces are declared with the ability to throw any exception from the implementation, but if not (like Runnable), wrapping (or catching) the checked exceptions into unchecked exceptions is the only way to go.

Standard Java exceptions

Defining your own exceptions

It is highly recommended that all user-defined exceptions are inherited from the RuntimeException class and fall into the class of unchecked exceptions (however, there are always exclusions from the rule). It is always a good idea to pass the informational message along with the exception as it helps a lot in troubleshooting production systems.

Documenting exceptions

Additionally, if the exception has been re-thrown due to another exceptional condition, the original exception must be preserved using the cause constructor argument. It will help other developers to implement proper exception handling and recovery (fallback) logic from the beginning and save them from the trouble of debugging in production systems.

Exceptions and logging

Download the Source Code

What’s next

To take advantage of the full power of available compute units, applications must be prepared to support multiple threads running concurrently and competing for resources and memory. In this part of the tutorial, we'll look at what Java can offer developers to help them write robust and secure applications in a concurrent world.

Threads and Thread Groups

Concurrent programming comes with many challenges related to data access and non-deterministic flow of events that can lead to unexpected crashes and strange failures. Not all thread states are clear right now, but we'll go over most of them later in the tutorial and discuss what kinds of events cause a thread to be in one state or another.

Concurrency, Synchronization and Immutability

Threads groups are intended as a nice feature, but are not recommended for use today as executors and thread pools (see Futures) are much better alternatives. Finally, the synchronization is Java re-entry: it means the thread can get a lock it already owns.

Futures, Executors and Thread Pools

But if the result of the execution is important, the standard Java library provides another abstraction to represent the computation that will occur at some point in the future, called Future. The result of theFuture may not be available immediately, so the application must wait for it using a series of get(. .) methods.

Locks

When a thread waits for the lock (obtained by another thread) using the lock() method call, it is in WAITING state. However, when a thread waits for the lock (obtained by another thread) using the tryLock() method call with timeout, it is in TIMED_WAITING state.

Thread Schedulers

If these two methods are called on the same class instance in two different threads via program execution, deadlock is very likely: the first thread will wait indefinitely for the lock2 acquired by the second thread, while the second thread waits indefinitely for the lock1 acquired by the first.

Atomic Operations

Concurrent Collections

Explore Java standard library

Using Synchronization Wisely

Wait/Notify

As such, it can cause subtle errors in the running program that will be very difficult and time-consuming to investigate.

Troubleshooting Concurrency Issues

Download

What’s next

In addition to the Java standard library, there are many serialization techniques and frameworks available: some of them use compact binary representation, others put readability first. Although we will mention many alternatives along the way, our attention will be concentrated on those of the Java standard library (and latest specifications): Serializable, Externalizable, Java Architecture for XML Binding (JAXB, JSR-222) and Java API for JSON- processing (JSON-P,JSR-353).

Serializable interface

This part of the tutorial is going to be devoted exclusively to serialization: the process of translating Java objects into a format that can be used to store and later be reconstructed in the same (or another) environment (http:// en.wikipedia.org /wiki/Serialization).Serialization not only allows saving and loading Java objects to/from persistent storage, but is also a very important component of modern distributed system communication. Moreover, it limits the flexibility to change the internal class representation, as it can break the serialization / deserialization process.

Externalizable interface

As we can see, the Serializable interface doesn't offer much control over what should be serialized and how (with the exception of transient keywords that mark the fields as non-serializable). The Externalizable interface allows a fine-grained serialization / deserialization adjustment in the cases when the simpler approach with Serializable interface does not work well.

More about Serializable interface

When the instances of this class are serialized, the classSerializationProxyExampleimplementation provides the replacement object (instance of the SerializationProxy class) instead. Consequently, when the instances of this class are being deserialized, theResolvemethod is called and SerializationProxy also provides the replacement, this time in the form of SerializationProxyExampleinstance.

Serializability and Remote Method Invocation (RMI)

The basic idea of ​​this pattern is to introduce a dedicated companion class for serialization (usually as a private staticinner class), which completes the class required to be serialized. It means that instances of the SerializationProxyExample class will never be serialized (and deserialized) directly.

JAXB

JSON-P

Still, it's a great thing, and the Java community is working to enrich JSON support by introducing the Java API for JSON Binding (JSON-B,JSR-367). With this API, serialization and deserialization of Java objects in/fromJSON should be as transparent as JAXB has.

Cost of serialization

Beyond Java standard library and specifications

Download the Source code

What’s next

Introduction

Reflection API

Annotations by themselves (except those from the standard Java library) have no effect on the code. The recent versions of the very popular Java specifications such as Java API for RESTful Web Services (https://jcp.org/en/jsr/detail?id=339), Bean Validation (https://jcp.org/en/ jsr/detail?id=349), Java Temporary Caching API (https://jcp.org/en/jsr/detail?id=107), Java Message Service (https://jcp.org/en/jsr/detail ?id=343), Java Persistence (https://jcp.org/en/jsr/detail?id=338) and many more are built on top of annotations and their implementations usually make heavy use of the Reflection API to collect metadata about the application being run.

Accessing generic type parameters

However, Java applications can use reflection to examine annotations present on various Java elements of interest at runtime and apply some logic based on the annotation and its attributes. Most of today's Java APIs include annotations that make it easier for developers to use and integrate them.

Reflection API and visibility

Reflection API pitfalls

Method Handles

Method Argument Names

Download the Source Code

What’s next

In this part of the tutorial our attention will be completely focused on scripting and dynamic language support in Java. One of the strengths of the dynamic languages ​​is that the program's behavior is defined at runtime, rather than at compile time.

Dynamic Languages Support

Since Java 7, the JVM has had direct support for modern dynamic (often called scripting) languages, and the Java 8 release has brought even more improvements to this space. These languages ​​include Ruby (https://www.ruby-lang.org/en/), Python (https://www.python.org/), and JavaScript (http://en.wikipedia.org/wiki/ JavaScript ) have gained great popularity and are currently the most widely used.

Scripting API

JavaScript on JVM

Groovy on JVM

Please note that the Groovyscripting engine has full access to the Java standard library and does not require additional bindings. It quickly became very popular due to the innovative language features similar to Java syntax and great interoperability with existing Java code.

Ruby on JVM

Python on JVM

The book 'Learn Python in a Day and Learn it Well' is written by Jamie Chan Powered by PyScriptEngine.

Using Scripting API

Download Code

What’s next

In this part of the tutorial, we will look at the Java Compiler API from 10000 feet. The Java Compiler API also supports annotation processing (see Tutorial Part 5, How and When to Use Enums and Annotations for more details, more in Tutorial Part 14, Annotation Handlers) and is split between three different packages shown below.

Java Compiler API

This API provides programmatic access to the Java compiler itself and allows developers to compile Java classes from source files on the fly from application code. More interestingly, we'll also walk through the Java compiler tree API, which provides access to the functionality of the Java syntax parser.

Annotation Processors

When dealing with more complicated examples, there are some subtle but very important details that can greatly speed up the compilation process.

Element Scanners

One way to invoke the scanner (and visitors) during the translation process is to use a note processor. The compilation process looks exactly as we saw in the Java Compiler API section.

Java Compiler Tree API

The initialization procedure became a little bit more complex, as we need to retrieve the instance of the Trees class and convert each element to tree path representation. The Java Compiler Tree API may look a little shallow, and it certainly is.

Download

To make it a bit more interesting, let's run it on all the source files we've experimented with so far: SampleClassToP arse.java and SampleClass.java. However, it gives full access to the abstract syntax trees and is a life saver when you need to do deep source code analysis and post-processing.

What’s next

Being compiler plugins also means that annotation processors are somewhat low-level and very dependent on the version of Java. But the knowledge of annotations from Part 5 of the tutorial How and When to Use Enums and Annotations and the Java Compiler API from Part 13 of the tutorial Java Compiler API will be very handy in understanding the intrinsic details of how the annotation processors work.

When to Use Annotation Processors

In this part of the tutorial, we're going to elucidate the magic of annotation processing, which is often used to inspect, modify, or generate source code driven solely by annotations. If used wisely, annotation processors can greatly simplify the lives of Java developers. That's why they are often bundled with many popular libraries and frameworks.

Annotation Processing Under the Hood

Essentially, any Java class could become a full-fledged annotation processor by implementing just a single interface: javax.annotation.processing.Processor. However, to become truly useful, any implementation of thejavax.annotation.processing.Processor must provide a public constructor with no arguments (for more details, see part 1 of the tutorial, Creating and Destroying Objects) that can be used to build the processor.

Writing Your Own Annotation Processor

The Java documentation points out that if a note processor instance is created and used without following the above protocol, the behavior of the processor is not defined by this interface specification. The class 'MutableClass' is annotated as @Immutable, but the field 'name' is not declared final. This confirms that the annotation processor has successfully detected an Immutablenotation abuse in a mutable class.

Running Annotation Processors

Nevertheless, the source file and its class have been generated using primitive string concatenations (and in fact this class is really very useless) the goal was to demonstrate how the code generation performed by annotation processors works so that more sophisticated generation techniques can be used.

Download the source code

What’s next

Introduction

Java Agent Basics

Java Agent and Instrumentation

Writing Your First Java Agent

And finally, we returned the new bytecode of the refactored version of the class so that it will be used by the JVM instead of the original one. In the next section of the tutorial, we'll cover one way to run the Java Agent alongside your Java applications.

Running Java Agents

The transformation we performed is quite naive, but it is here for demonstration purposes. Second, we found the HttpURLConection class and changed all of its constructors to put the statement System.out.println(this.getURL());

Download the source code

What’s next

Gambar

Table 1.1: datasheet
Table 1.2: datasheet
Table 2.1: datasheet
Table 2.2: datasheet
+7

Referensi

Dokumen terkait

public InsertSql(String table, Column[] columns, Object[] fields) @Override public String generate().. private String valuesList(Object[] fields, final Column[]

public class Daftar_kartu extends Activity {. private static

As an example, any Java program that uses strings is using objects created from the String class. This class contains attributes that determine what a String object is and

package Big_Cat; class Big_Cat package bigCat; // Kelas abstrak public abstract class Big_Cat { protected static String name; protected abstract void eat; } // Kelas turunan class

Below is the definition of the Pen class: public class Pen{ private String colour; private boolean hasEraser; private int tipType; public PenString colour, int tipType, boolean

3 package A; public class MainA { public static void mainString args[]{ } } package A; public class TestA { private int varPrivateA ; int varDefaultA ; protected int

• “Object” means a particular item that belongs to a class – Also called an “instance” • Example String s1 = "Hello"; – Here, String is the class, and the variable s1 and the value

Java Application Menampilkan Tulisan //Welcome1.java Public class Welcome1 { //main method memulai eksekusi aplikasi java public static void main String args[] {