Misunderstandings about abstract keyword

The reason is that I hand-written a JUnit4 test class:

import org.junit.*;
import static org.junit.Assert.*;
public class MyTest
{
@Test
public void testAbc() {
assertEquals(1, 1);
}
}

Then run and report an error

java -cp lib/junit-4.13.2.jar;.junit.textui.TestRunner MyTest
.F
Time: 0.005
There was 1 failure:
1) warning(junit.framework.TestSuite$1)junit.framework.AssertionFailedError: No tests found in MyTest

Modify so that the class inherits the TestCase class:

import org.junit.*;
import junit.framework.TestCase;
import static org.junit.Assert.*;

public class MyTest extends TestCase
{
  //The inside remains unchanged
}

Now it’s OK (in fact, there are problems with this code modification method and the main class called from the command line, which is equivalent to mixing JUnit3)

java -cp lib/junit-4.13.2.jar;.junit.textui.TestRunner MyTest
.
Time: 0.003

OK (1 test)

Then I took a look at the source code of the TestCase class and found that it is an abstract class:

public abstract class TestCase extends Assert implements Test {
    //slightly...
}

The thought in my mind at that time was: Since it is an abstract class, there must be at least one abstract method for subclasses to implement. However, the methods in MyTestCase are all handwritten test methods (testXXX), and there are no methods specifically overridden in the parent class. Why can MyTestCase be compiled successfully? What the hell?

I searched for a long time in the TestCase class source code, but I really couldn’t find the abstract method!

So at this time I thought:Can it be marked as an abstract class if there is no abstract method?

Quickly write a class and try:

public abstract class Abs
{
}

Sure enough, the compilation passed! Why? Could it be that I didn’t read the book carefully before, which led to incorrect understanding?

So I dug out the 4th edition of James Gosling’s “The Java Programming Language” and found the corresponding chapter.

3.7 Abstract classes and abstract methods

Object-oriented programming has an extremely useful feature: the concept of abstract classes. By using abstract classes, you can declare a class that defines only part of the implementation, and leave some or all of the methods to extension classes that provide specific implementations. The opposite of abstraction is concrete. A class with only concrete methods is called a concrete class. These concrete methods also include the implementation of abstract methods inherited from the super class.

Abstract classes are useful in situations where some behavior is specific to most or all objects of a certain type, while other behavior makes sense only to some classes but not to a general superclass. Such a class can be declared abstract, and all unimplemented methods in this class are marked abstract. (If you want to define some methods but don’t want to give any implementation, you may need an interface, see Chapter 4)

Next is an example of a benchmark suite. It knows how to drive and measure, but it has no way of knowing in advance what benchmarks to run. Most abstract classes match the “template method” design pattern. In most cases, template methods can be modified with final to prevent tampering.

abstract classBenchmark

{

abstract void benchmark();

public final long repeat(int count) {

long start = System.nanoTime();

for (int i = 0; i < count; i + + )

benchmark();

return (System.nanoTime() – start);

}

}

As long as a class contains an abstract method, it must be declared abstract. Although this is somewhat redundant, the advantage is that readers do not need to scan all the methods in a class to determine whether the class is abstract. [Note: Although this paragraph makes it clear that “as long as there are abstract methods, it must be an abstract class”, it does not say “as long as it is an abstract class, there will be abstract methods.” So I misunderstood here. In addition, the word redundant is also very subtle. It describes “declaring a class as abstract”. It feels like the abstract declaration of a class is just an accessory. 】

[Omit two paragraphs. . . 】

Any class can override methods inherited from the superclass and declare them as abstract. This technique is useful, for example, when the default implementation of the superclass is not valid for this subclass.

You cannot create an abstract class because this will cause some method calls to not find the implementation. [Note: But if there is no abstract method in this abstract class, it should be no problem. It is estimated that Java saves this runtime detection]

The book only says so much, and it’s still a bit vague. Look for the Java language specification, the link is Chapter 8. Classesicon-default.png?t=N7T8https://docs.oracle.com/javase/specs/ jls/se17/html/jls-8.html#jls-8.1.1.1

The first sentence is very vague, “It is considered incomplete”. Does the programmer or the compiler think it is incomplete?

An abstract class is a class that is incomplete, or to be considered incomplete.

Some examples are given later, but they do not explain under what circumstances a class without abstract methods is declared abstract.

However, it is specifically mentioned that abstract is used to supplement the implementation of subclasses. If you don’t want people to instantiate your class, instead of adding abstract to the class, just leave a private no-argument constructor and never use it. Call it. (Java 1.6 already has this paragraph)

The virtual machine specification does not seem to mention the relationship between the ACC_ABSTRACT flags of classes and methods.

Chapter 4. The class File Format (oracle.com)icon-default.png?t=N7T8https://docs.oracle.com/javase/specs/jvms/ se17/html/jvms-4.html#jvms-4.10

I guess you have to read the JUnit documentation to find out the author’s intention of adding abstract to TestCase.

However, TestCase is a JUnit3 class and is too old. I very much doubt that this is the Java code style ten years ago, that is, the author specifically added abstract to this entity class in order to prevent users from directly instantiating an entity class.

In addition, I also found an Oracle Java tutorial (this tutorial was written in Java 8 and they will no longer maintain it)

Learning the Java Language > Interfaces and Inheritance) (oracle.com)”>Abstract Methods and Classes (The Java? Tutorials > Learning the Java Language > Interfaces and Inheritance) (oracle.com)\https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html clearly states that abstract classes do not need to contain abstract methods: An abstract class is a class that is declared abstract-it may or may not include abstract methods.

However, this statement is also very vague. What if its abstract method is inherited?

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Java skill treeBasic syntax of JavaKeywords in Java 136791 people are learning the system