Class inheritance

Why program for interfaces? Is inheritance hard to use? Is it because Java is single-inheritance that interfaces are developed to implement so-called multi-inheritance? First, succession is a double-edged sword.

Benefits of inheritance:

  1. Code reuse, common attributes and methods can be dropped into the base class, and subclasses only need to focus on subclass-specific ones.
  2. Base classes make it easy to work uniformly with different subclasses, such as transition objects.

Inheritance pain points

  1. It destroys encapsulation, which is one of the three characteristics of object programming and the basic thinking of object programming. So how does that break the encapsulation? If A subclass wants to override (extend) A method of its parent class, it needs to know the implementation details of the method in the base class, and it needs to understand the dependencies between methods in the parent class. For example, if the subclass wants to override A method in the parent class, and A method in the parent class calls A method in the parent class, then it needs to look at the implementation details in the B method. Otherwise, errors may occur. Ignore the examples. Similarly, if you want to modify a method in a parent class, consider subclasses as well. This breaks encapsulation. As shown in figure:

2. Damage the IS-A relationship. The inheritance relationship is the IS-A relationship. So where does the destruction begin? For example, if you have a base class called birds and a method called fly() in it, the subclass overrides that method to implement a specific function. As the name implies, the base class expects the subclass to have the ability to fly, but what if one of the subclasses is a penguin, and it can’t fly, but can only swim and walk? “Swim” in the penguin “fly()”? This is fine, but it clearly undermines the IS-A relationship. A subclass may not have the same properties and behaviors as a parent class, but a subclass can override methods to implement behavior that is inconsistent with what the parent class expects. For example, if you call fly() in the hope of flying out of the base class, you end up swimming… Example may not be appropriate, but understand the meaning of OK!

Okay, so what’s the solution?

  1. Use final to specify classes or methods that cannot be inherited.
  2. Use composition instead of inheritance. Code can be reused, but subclasses cannot be handled uniformly through base classes.
  3. Using interfaces finally speaking of interfaces!

In many cases we focus only on what is implemented, not what type implements it. For instance heat, induction cooker is ok, gas range also goes, rural range also goes. So you can separate out the function and make an interface, like a heating interface. Using interfaces can reduce code coupling, which is to address the point where inheritance breaks encapsulation, as well as breaking THE IS-A relationship (because there is no inheritance, there is no IS-A). Although unified management can be achieved by using the interface, but there is no implementation method in the interface, so it can not solve the problem of code reuse. Therefore, the ultimate solution — interface + composition.

The nature of interfaces

When do we use interfaces? In some scenarios, we don’t need to care about the type, just the functionality implemented. For example, heating, microwave oven, induction cooker, gas stove can be heated, but I only want to heat this function (ability) OK. Java8 and 9 have enhanced interfaces. Java8 allows two new classes of methods to be defined in interfaces :1. Static methods 2. The default method, both of which must be public. Up to this point, methods in the interface started with public Abstract. Prior to Java8, when static methods could not be defined in interfaces, related static methods could only be defined in separate classes. For example, in the Java API, the Collection interface has a separate class, Collections. The default method and the original abstract method is different, the default method has a default implementation, implementation class can change the implementation or not change, this is to facilitate the increase of interface functions. In Java9, static methods and default methods are allowed to be private. This makes it easy to reuse code in multiple static and default methods, and it makes sense, given the nature of encapsulation we’ve seen before, why Java8 didn’t do it this way in the first place.

An abstract class

An abstract class can contain either abstract or concrete methods. Abstract classes, like interfaces, cannot be used to create objects directly. Abstract classes express concepts of things. Why do we have to use abstract classes? I just learned when also very confused, directly in the concrete class with an empty method body not to solve it? In fact, the use of an abstract class is in order to let the user must implement the abstract methods in succession, can’t be ignored, in the same way, using the abstract class, it is necessary to use a subclass of the abstract class to create an object, rather than using function may not complete an abstract class, this is done to reduce the error, can be said to be a less errors of mechanism of Java. Abstract classes, much like interfaces, cannot create objects directly, especially if they are filled with abstract methods! In fact, they are a partnership rather than a substitute. An interface will have a corresponding abstract class. For example, a Collection interface corresponds to AbstractCollection. All or parts of this abstract class implement all the abstract methods in the interface. From a consumer perspective, to use this interface, you can either implement the interface directly or inherit its corresponding abstract class, then further override methods and implement abstract methods that are not implemented in the abstract class as needed. In one case, if the class using the interface already has an inherited class, only all abstract methods in the interface can be implemented under single inheritance. Finally, we got through here.

abnormal

Return (); return (); return (); A return is returned to the upper caller, but the code executed after the throw is undefined, dynamically determined by the exception-handling mechanism. NullPointerException is a NullPointerException object. If the NullPointerException object is NullPointerException, the program will not continue to execute. At this point, the exception handling mechanism will be started. If the current function is not present, it will look up to the main function. If it is not present, it will use the default mechanism, which is to output the exception stack information and exit. Exit means that the code after the exception point is not executed. Exception class, the base class is Throwable. It has two direct subclasses :Error and Exception. An Error is a system Error or resource exhaustion that Java handles itself and does not need to be thrown or handled in the application. There are three direct subclass Exception: IOException, RuntimeException, SQLException. Of all exceptions, only RuntimeException is unchecked; the others are checked. Unchecked exceptions indicate program logic errors, and programmers should check for bugs rather than trying to handle exceptions. A checked exception is a program that has no problem but is caused by an unpredictable error such as a database and should be handled by the caller. An exception can also be rethrown in a catch block, either as the original or as a new exception. Why rethrow the exception? Because the current code does not fully handle the exception, further processing is required by the caller. Why throw a new exception? Because the current exception is not appropriate, inappropriate may be insufficient information, need to add new information. It can also be too detailed for the caller to understand and use, although if the caller wants to know the details, he can get the original exception by using getCause(). When it comes to getCause(), we are talking about exception chains. The Throwable class constructor has two main arguments: 1.message, which represents the exception message, and 2.cause, which represents the other exception that triggered the exception. The exception at the top is triggered by the exception at the bottom, which is denoted by cause, thus forming a chain of exceptions. It is best not to write a return or throw an exception in finally. In general, if an exception is caught at your level and can’t be fully resolved, throw it at your superior. If your superior can’t fully resolve it, he should throw the information he got along with the new information to a higher level until the big boss takes charge and deals with it. Each level can neither gloss over the problem nor shirk its share of responsibility. Day8 Study notes chapter 7 common basic class wave a few days finally began to see this chapter, estimate notes also a lot, can send a blog roar roar ~

A wrapper class

Java5 has since introduced automatic boxing and unboxing to assign primitive types directly to reference variables. Automatic unboxing and boxing are provided by the Java compiler and replaced by the corresponding valueOf/xxxValue. All wrapper classes override the equals, hashCode, and toString methods of Object. Equals actually compares the primitive type values it wraps, noting that it returns true only if the binaries of two floats are identical. Since hashCode is calculated based on objects, it is obvious that if the equals of two objects are the same, then hashCode must be the same, and vice versa, since address collisions can occur, such as chained addresses. If you subclass equals, you must override hashCode. If you subclass equals, you must override hashCode. If you subclass equals, you must override hashCode. Java uses UTF-16 internally, which brings us to Unicode, which was created to solve the problem of different scripts around the world. Unicode encodes megabytes of characters, but that’s all it does. It doesn’t dictate how numbers are mapped to binary. Utf-8,UTF-32,UTF-16, and so on are all encoded or mapped. An int can represent any Unicode character. The integer number in Unicode is called a code point, which represents a Unicode character, and a corresponding code unit. There’s a part of Character that deals with code points, code units, Character, Unicode… I didn’t read this part closely, it was a bit boring, so I skipped it… The String class uses an array of characters to represent a String. The String creates a new array of parameters and copies the contents of the parameters into the array. It does not use the array of parameters directly. Like the wrapper class, the String class is immutable and cannot be inherited, and the internal char array value is final. What looks like modification in String is actually done by creating new arrays. For example, concat() creates a new array and assigns values to the new array. Of course, this is inefficient, so StringBuilder and StringBuffer(thread-safe) are commonly used. String has a pool of String constants, and when you use a String as a constant, you use the same String object in the pool. Behind the String + and +=, the Java compiler generates a StringBuilder and converts it to append.

The generic

Generics are broad types that extend the interface further so that code is no longer bound to the data types they can operate on. The same set of code can be used for multiple data types, reusing code, reducing coupling, improving readability and security, which we’ll talk about later. Generics are parameterization of types, processing data types that are not fixed but can be passed in as parameters. When I first came to generics, I wondered why I had to define type parameters, define ordinary classes, and just use Object. Internally, the compiler converts generic code to plain non-generic code, wipes out the type parameter T and replaces it with Object, plus the necessary casts, and then the Java virtual machine only knows the plain class code when it executes. So back to the question, why use generics when you end up converting to Object? For readability and security, for example, public class Pair{omit}.Pair = new Pair(” ha ha “,1); Integer ID = (Integer)pair.getFirst(). If you write it this way, it will compile fine, but run it with an error. If you use generics here, you can avoid the error and make it readable :Pair Pair =new Pair<>(” ha ha “,1). The most common use of generic classes is as container classes, which are classes that hold and manage multiple pieces of data. A generic method does not matter if the class in which it is called is generic. You do not need to specify the actual type of the type parameter when calling a generic method. The compiler can infer that automatically. Generic interfaces Interfaces can also be generic, specifying specific types in the class that implements the interface. In previous generics, type parameters were treated only as objects, but we could actually define an upper bound on the parameter. The upper bound could be a concrete class, a concrete interface, or even other type parameters. Both use the extends keyword.

The wildcard

To be continued.

Java Programming Logic