thinking in java summary

This book was designed with careful consideration of the way people learn the Java language. When I was teaching, the students' feedback effectively helped me recognize which parts are more difficult and need special attention. I've also covered too many problems at one time, but the lesson learned is that if you include a lot of new features, you need to explain them all, which is especially easy to deepen the confusion of students. Therefore, I have made a great effort to make this book cover as few issues as possible at a time. So, my goal in the book is to have each chapter cover a language feature, or just a handful of interrelated features. This makes it easier for readers to digest what they have learned before moving on to the next topic. Listed below is a brief description of the chapters in this book as they correspond to my actual classroom teaching.
(1) Chapter 1: Introduction to Objects
This chapter is an overview of object-oriented programming (OOP), including answers to basic questions such as "what is an object?" and encapsulation, messages and functions, inheritance and composition, and very importantly, the concepts of polymorphism. This chapter will ask you some basic questions about object creation, such as constructors, where objects exist, where to put them after creation, and the magic garbage collector (which can clean up objects that are no longer needed). Other issues to be covered include error control mechanisms through exceptions, multithreading for a responsive user interface, networking and the Internet, and more. You'll also learn what makes Java special, why it's been so successful, and issues related to object-oriented analysis and design.
(2) Chapter 2: Everything is an Object
This chapter takes you to the point where you can start writing your first Java program, so some basic concepts must be explained, including the concept of an object "handle"; how to create a Objects; an introduction to primitive data types and arrays; scope and how the garbage collector cleans up objects; how everything in Java comes under a new data type (class), and how to create your own; functions , arguments, and return values; visibility of names and use of components from other libraries; the static keyword; comments and embedded documentation, and more.
(3) Chapter 3: Control Program Flow
This chapter begins with a description of all the operators that Java inherited from C and C++. In addition, learn about some of the subtler issues with operators, as well as issues involving styling, promotion, and prioritization. Then we will talk about the basic flow control and selection operation, which are the characteristics of almost all programming languages: use if-else to realize selection; use for and while to realize loop; use break and continue and Java's label break and continues (these are considered the "missing gogos" in Java) to exit loops; and switches to implement another form of selection. Although these have some commonalities with those seen in C and C++, there are some differences. Otherwise, all examples are complete Java examples, allowing you to quickly familiarize yourself with the look and feel of Java.
(4) Chapter 4: Initialization and Cleanup
This chapter begins with the introduction of builders, whose role is to guarantee correct implementation of initialization. The definition of a builder involves the concept of function overloading (since there may be several builders at the same time). Next up is the removal process, which isn't necessarily as simple as it might seem. When you're done with an object, you can usually leave it alone, and the garbage collector will automatically step in to release the memory it occupies. The Garbage Collector and some of its characteristics are discussed in detail here. At the end of this chapter, we'll take a closer look at the initialization process: automatic member initialization, designated member initialization, order of initialization, static (static) initialization, array initialization, and more.
(5) Chapter 5: Hiding the Implementation
This chapter discusses how code is encapsulated together and why parts of the library are exposed when other parts of the library are hidden. The first thing to discuss is the package and import keywords, which perform file-level encapsulation (packaging) operations and allow us to build libraries of classes (class libraries). The issue of directory paths and file names is also discussed at this point. The remainder of this chapter discusses the public, private, and protected keywords, the concept of "friendly" access, and the meaning of different levels of access control in various situations.
(6) Chapter 6: Class Regeneration
The concept of inheritance is an important part of almost all OOP languages. It's an efficient way to take an existing class and add new functionality to it (while modifying it, which is the topic of Chapter 7). When reusing existing code through inheritance (regeneration), you generally need to keep the "base class" unchanged and just string things together here and there to achieve the desired effect. However, inheritance is not the only means of making new classes based on existing classes. With "composition", it is also possible to embed an object into a new class. In this chapter, you will learn about these two methods of reusing code in Java and how to use them.
(7) Chapter 7: Polymorphism
If you do it by yourself, it may take 9 months to discover and understand the problem of polymorphism, which is actually an important foundation of OOP. Through some small, simple examples, the reader can know how to create a series of types through inheritance, and operate on the objects in that series through their common base class. Through Java's concept of polymorphism, all objects in the same family have commonality. This means that the code we write no longer has to rely on specific type information. This makes the program more scalable and more inclusive. As a result, program construction and code maintenance can become more convenient, and the price paid will be lower. In addition, Java also provides a third way to set the reproduction relationship through the "interface". The so-called "interface" here is a pure abstraction of the physical "interface" of the object. Once the concept of polymorphism is understood, the meaning of an interface is
easy to explain. This chapter also introduces you to Java 1.1's "inner classes."
(8) Chapter 8: Containment of Objects
For a very simple program, it may only have a fixed number of objects, and the "time to live" or "time to live" of the objects is known. But often, our programs create new objects at indeterminate times, and their details are only known when the program is running. Furthermore, there is no way of knowing how many objects are needed, or even their exact types, except at runtime. To solve this common programming problem, we need to have the ability to create any number of objects at any time, anywhere. The purpose of this chapter is to explore some of the Java tools used to hold objects while working with them: from simple arrays to complex collections (data structures) such as Vector and Hashtable. Finally, we'll dig into the new and improved Java 1.2 collections libraries.
(9) Chapter 9: Exception Error Control
One of the most fundamental design tenets of Java is that code that is organized incorrectly will not actually run. The compiler tries to catch problems as much as possible. But in some cases, the problem will not be found until it enters the runtime. These problems are either programming errors or some natural error conditions that only exist as part of the normal operation of the program. Java provides a "violation control" mechanism for this purpose, which is used to control all problems that arise when the program is running. This chapter explains how the try, catch, throw, throws, and finally keywords work in Java. It also tells when a violation should be "thrown" and what action should be taken when a violation is caught. In addition, you will also learn some standard violations of Java, how to build your own violations, what to do when a violation occurs in the builder, and how to locate the violation controller, etc.
(10) Chapter 10: Java IO System
In theory, we can divide any program into three parts: input, processing and output. This means that IO (input/output) is the most critical part of any program. In this chapter, you will learn the various classes that Java provides for this purpose, how to use them to read and write files, memory blocks, and the console. The "old" IO and the "new" IO of Java 1.1 will be highlighted. Among other things, this section discusses how to take an object, "stream" it (so that it can be placed on disk or sent over a network), rebuild it, and so on. These operations can be done automatically in version 1.1 of Java. Also, we'll discuss the Java 1.1 compression library, which will be used in the Java archive format (JAR).
(11) Chapter 11: Runtime Type Identification
Java's Runtime Type Identification (RTTI) allows us to know what the exact type of an object is if we only have a handle to the underlying class. In general, we need to intentionally ignore the exact type of an object and let Java's dynamic binding mechanism (polymorphism) implement the correct behavior for that type. But in some cases, for an object with only one underlying handle, it is still particularly necessary for us to know what its exact type is. Once you have this information, you can often perform a special case operation more efficiently. This chapter explains what RTTI is for, how to use it, and how to discard it when appropriate. Additionally, the "reflection" feature of Java 1.1 is covered here.
(12) Chapter 12: Passing and Returning Objects
Since the only way we communicate with objects in Java is "handles", the concept of passing an object into a function and returning an object from that function is very interesting. This chapter explains what you need to know in order to manage objects as you move in and out of functions. It will also cover the concept of the String class, which solves the same problem in a different way.
(13) Chapter 13: Creating Windows and Applets
Java comes with the Abstract Windows Toolkit (AWT). This is actually a collection of classes that solve window manipulation problems in a portable form. These windowed programs can appear as program slices or as stand-alone applications. This chapter will introduce you to AWT and the process of creating online applets. We'll also explore the pros and cons of the AWT and some of the GUI improvements in Java 1.1. Also, the important "Java Beans" technology will be highlighted here. Java Beans are an important foundation for creating Rapid Application Development (RAD) program construction tools. The last thing we covered was the "Swing" library for Java 1.2 -- which made Java's UI components significantly improved.
(14) Chapter 14: Multithreading
Java provides a set of built-in mechanisms that provide support for multiple concurrent subtasks, which we call "threads". These threads all run within a single program. Unless the machine has multiple processors installed, this is the only way multiple subtasks will work. While there are many other important uses, the use of multithreading is especially important when you intend to create a responsive user interface. For example, after adopting multi-threading technology, although there are other tasks being executed at the time, the user can still press a button or type some text without hindrance. This chapter will discuss Java's multithreading mechanism and introduce related syntax.
(15) Chapter 15 Network Programming
When you start writing network applications, you will find that all Java features and libraries seem to have been connected together. This chapter explores how to communicate over the Internet, and some of the classes Java uses to aid in this type of programming. In addition, it also shows how to create a Java applet that communicates with a "Common Gateway Interface" (CGI) program; reveals how to write a CGI program in C++; and describes Java 1.1's "Java Database Connection" ( JDBC) and Remote Method Invocation (RMI).
(16) Chapter 16 Design Paradigms
This chapter discusses very important, but also unconventional, "paradigm" programming concepts. You will learn an example of the design progression process. The first is the initial plan, and then through various program logics, the plan is continuously reformed into a more appropriate design. Through the whole process of learning, everyone can experience a way to make design ideas gradually clear.
(17) Chapter 17 Projects
This chapter contains a series of projects that either build on or expand on what was covered earlier in the book. These projects are clearly the most complex in the book, and they effectively demonstrate the application of new technologies and class libraries. Some topics do not seem to fit in the heart of this book, but I found it necessary to discuss them in teaching, and these topics are placed in the appendix of this book.
(18) Appendix A: Using non-Java code
For a Java program to be fully portable, it must have some serious flaws: it is too slow and cannot access platform-specific services. If you know in advance what platform the program will be used on, you can consider turning some operations into "intrinsic methods", which can significantly speed up execution. These "intrinsic methods" are actually special functions written in another programming language (currently only C/C++ is supported). Java also provides support for non-Java code in other ways, including CORBA. This appendix will detail these features so that you can create some simple examples that work with non-Java code.
(19) Appendix B: Comparing C++ and Java
For a C++ programmer, he should have mastered the basic concepts of object-oriented programming, and Java syntax is undoubtedly very familiar to him. This is evident because Java itself was derived from C++. However, there are some notable differences between C++ and Java. These differences represent a major improvement on Java over C++. Once you understand these differences, you can understand why Java is a great language. This appendix was created for this purpose, and it describes some of the important features that distinguish Java from C++.
(20) Appendix C: Java Programming Rules
This appendix provides a lot of suggestions to help you with low-level programming and code writing.
(21) Appendix D: Performance
Through the study of this appendix, you can find the bottlenecks in your Java programs and effectively improve the execution speed.
(22) Appendix E: Some words about garbage collection
This appendix describes the operations and methods used to implement garbage collection.
(23) Appendix F: Recommended Reading
Lists a list of Java reference books that I find particularly useful.

Chapter 2 Everything Is an Object
Through the study of this chapter, you have been exposed to enough Java programming knowledge and know how to write a simple program by yourself. In addition, I have a certain degree of understanding of the general situation of the language and some basic ideas. However, the patterns for all the examples in this chapter are one-liners of "do this, do that, and then do something else." If you want the program to make a choice, how should you design it? For example, "If the result of doing this is red, do that; if not, do something else." For this basic programming method, the next chapter will detail how it is implemented in Java.

Chapter 3 Controlling Program Flow
This chapter summarizes the basic features that most programming languages ​​have: calculation, operator precedence, type conversion, selection and looping, and so on. We are now ready to move on to the realm of object-oriented programming. In the next chapter, we will discuss the initialization and cleanup of objects, and then we will describe the hidden basic implementation methods later.

Chapter 4 Initialization and Cleanup
As a specific operation form of initialization, the constructor should make everyone clearly feel the importance of initialization in the language. Like C++ programming, the key to judging the efficiency of a program is whether serious programming errors (bugs) are caused by incorrect initialization of variables. These forms of errors are difficult to spot, and similar issues apply to improper removal or finishing work. Since constructors allow us to guarantee proper initialization and cleanup (the compiler disallows object creation without proper constructor calls), we gain full control and safety. In C++, the work of "destruction" (Destruction), which is opposite to "construction", is also quite important, because objects created with new must be cleared explicitly. In Java, the garbage collector automatically frees memory for all objects, so the equivalent cleanup method in Java is not always needed.
If builder-like behavior is not required, Java's garbage collector can greatly simplify programming and add greater safety to the memory management process. Some garbage collectors can even clean up other resources, such as graphics and file handles. However, the garbage collector does add runtime overhead. But it's hard to see how much of an impact this overhead has had, since the overall Java interpreter is still relatively slow so far. As this situation improves, we should be able to tell if the overhead of the garbage collector makes Java unsuitable for certain jobs (one of the problems is the unpredictable nature of the garbage collector). Since all objects are guaranteed to be constructed correctly, there is actually much more to the builder than is described here. In particular, when we generate new classes through "authoring" or "inheritance", the guarantee of construction still holds, and some additional syntax is required to provide support for it. You'll learn more about creation, inheritance, and how they affect builders in later chapters.

Chapter 5
The most important thing in any relationship is to set boundaries or rules that all parties must abide by. When you create a library, you establish a relationship with users of that library ("client programmers")—those users are other programmers who may use our library to build an application themselves, or use our library to build a larger library. If you don't formulate rules, client programmers can manipulate all members of a class as they like, whether we want some of them to be directly manipulated or not. Everything is exposed in front of others. This chapter describes how to structure classes to make an ideal library. First, we describe how to encapsulate a set of classes into a library. Second, we describe how a class controls access to its own members.
Typically, a C program project will start breaking somewhere between 50K and 100K lines of code. This is due to the fact that C has only one "namespace", so names start to collide with each other, causing additional management overhead. Whereas in Java, the package keyword, package naming scheme, and import keyword provide us with full control over the names, so the problem of naming conflicts can be easily avoided. There are two reasons for us to control access to members. The first is to prevent users from accessing tools they shouldn't. Those tools are necessary for the internal mechanism of the data type. But they are not part of the user interface, and users don't have to use it to solve their own specific problems. Therefore, making methods and fields "private" can greatly facilitate users. Because they can easily see what is most important to them and what they need to ignore. This simplifies the user's understanding of a class. The second and most important reason for access control is to allow library designers to change the inner workings of a class without worrying about how it might affect client programmers. In the beginning, you can build a class in one way, and later find that you need to restructure the code to achieve faster speed. If the interface and implementation details have already been clearly separated and protected, you can easily achieve your own goals without requiring users to rewrite their code.
With access specifiers in Java, the creator of a class can be effectively controlled. Users of that class know exactly which ones they can use and which ones they can ignore. But more importantly, it ensures that no user can rely on any part of a class's underlying implementation mechanism. As a class creator, we are free to modify the underlying implementation details, and this change has no impact on client programmers, since they do not have access to that part of the class. Having the ability to change basic implementation details gives you the freedom to "make mistakes" in addition to being able to improve your setup later. No matter how carefully planned and designed, some mistakes are still possible. Knowing that you can make this mistake quite safely, you can feel free to experiment more and more freely. This is very helpful to improve my programming level, so that the whole project can be completed faster and better in the end.
The public interface of a class is visible to all users, so it is the most important part that should be as accurate as possible during analysis and design. But don't be too nervous, a little error is still allowed. If there is a slight problem with the originally designed interface, consider adding more methods, as long as you don't delete things that client programmers are already using in their code.

Chapter 6 Class Regeneration
Regardless of inheritance or synthesis, we can create a new type based on an existing type. But typically, we use composition to "regenerate" or "reuse" an existing type as part of the process of implementing a new type's base. But if you want to achieve "regeneration" of the interface, you should use inheritance. Since the derived or derived class has the interface of the base class, it can be "upcasted" to the base class. This is crucial for the polymorphic problem to be dealt with in the next chapter.
Although inheritance gets a lot of emphasis in object-oriented programming, when actually starting a design, it's best to consider composition first. Inheritance should only be considered when absolutely necessary (we'll return to this issue in the next chapter). Synthesis appears to be more flexible. However, by applying some inheritance tricks to your own member types, you can change the type of exactly those member objects at runtime, and thus change their behavior.
Although for rapid project development, code regeneration through composition and inheritance is of great help. But you generally want to redesign your class structure before allowing other programmers to rely entirely on it. Our ideal class structure should be that each class has its own specific purpose. They cannot be too large (such as integrating too many functions, it is difficult to realize its regeneration), nor too small (so that they cannot be used by themselves, or new functions cannot be added). The final implemented class should be able to reproduce easily.

Chapter Seven Polymorphism
"polymorphism" means "different forms". In object-oriented programming, we have the same facade (common interface to base classes) and different forms of using that facade: dynamically bound or organized, different versions of methods. Through the study of this chapter, you already know that without using data abstraction and inheritance techniques, it is impossible to understand, or even create an example of polymorphism. Polymorphism is a feature that cannot be applied independently (like a switch statement), only in conjunction with other elements. We should treat it as part of the class's overall relationship. People often confuse other, non-object-oriented features of Java, such as method overloading, which sometimes share some of the characteristics of object-oriented. But don't be fooled: if there is no binding later, it's not polymorphism.
In order to use polymorphism and even object-oriented techniques, especially in your own programs, you must expand your programming horizons to include not only the members and messages of a single class, but also the consistency between classes and their Relationship. Although this requires more energy when learning, it is very worthwhile, because only in this way can you really effectively speed up your programming speed, organize your code better, make it easier to make programs with a wide range of tolerance, and make it easier for you to understand. Maintain and extend your own code.

Chapter 8 Object Containment
Let's review the collections provided by the standard Java (1.0 and 1.1) libraries (BitSet is not included here because it is more like a class with a special mission):
(1) Arrays contain objects' Digital index. It holds objects of a known type, so when looking up an object, you don't have to cast the result. Arrays can be multidimensional and can hold primitive data types. However, once it is created, the size cannot be changed.
(2) Vector (vector) also contains the object's numerical index - can think of arrays and Vector as a random access collection. Vector can automatically resize itself as we add more elements. But Vector can only hold object handles, so it cannot contain basic data types; and when an object handle is taken out of the collection, the result must be shaped.
(3) Hashtable (hash table) is a type of Dictionary (dictionary), which is a way to associate objects (rather than numbers) with other objects. The hash table also supports random access to objects. In fact, its entire design highlights the "high speed" of access.
(4) Stack (stack) is a "last in first out" (LIFO) queue.
If you've ever been familiar with data structures, you might have wondered why you didn't see a larger set. From a functional point of view, do you really need a larger set? For Hashtable, you can put anything into it and retrieve it very quickly; for Enumeration (enumeration), you can traverse a sequence and take a specific operation on each element in it. That's a powerful enough tool. But Hashtable has no concept of "order". Vectors and arrays give us a linear order, but inserting an element in the middle of any of them generally comes at a "heavy" price. Among other things, queues, unstack queues, priority queues, and trees all involve "ordering" elements -- not just putting them in so that they can be found or moved later in linear order. These data structures are also very useful, which is why they are included in Standard C++. For this reason, the collection of standard Java libraries should only be considered a starting point for yourself. And if you must use Java 1.0 or 1.1, you can use JGL when you need to go beyond them. If you can use Java 1.2, you can just use the new collections, which generally meet all our needs. Note that this book spends a lot of space on Java 1.1, so a large number of collections used in the book are those that can only be used in Java 1.1: Vector and Hashtable. For now, this is an unavoidable approach. However, doing so also provides better backward compatibility with older Java code. When writing new code in Java 1.2, the new collections will often serve you better.

Chapter 9 Violation Error Control
Through advanced error correction and recovery mechanism, we can effectively enhance the robustness of the code. Error recovery is a fundamental consideration for every program we write. It is especially important in Java because one goal of the language is to create different program components for use by other users (client programmers). In order to build a robust system, each component must be very robust. In Java, the purpose of exception control is to use as streamlined code as possible to create large, reliable applications, while eliminating those uncontrollable errors in the program. The concept of violations is difficult to grasp. But only by using it well, can one's own project obtain significant benefits immediately. Java enforces compliance with all aspects of violations so that both library designers and client programmers can use it consistently.

Chapter 10 Runtime Type Identification RTTI
Use RTTI to investigate type information based on an anonymous base class handle. But for this reason, it is very easy for newcomers to misuse it, because sometimes the polymorphic approach is enough. For those previously accustomed to procedural programming, it is extremely easy to organize their programs as a series of switch statements. They could do this with RTTI, thereby losing significant value of polymorphism in code development and maintenance. Java's requirement is that we use polymorphism as much as possible, and only use RTTI in very special cases. But in order to take advantage of polymorphism, we are required to have control over the definition of the base class, because sometimes within the scope of the program, it may be found that the base class does not include the methods we want. If the base class comes from a library, or is controlled by something else, RTTI is a good solution: you can inherit a new type, and then add your own extra methods. Elsewhere in your code, you can detect your own particular type and call that particular method. Doing so does not destroy polymorphism and the extensibility of the program, because the addition of new types does not require looking for switch statements in the program. But when you add new code in the body that requires new features, you must use RTTI to detect your own specific types.
From the perspective of the interests of a particular class, adding a feature to a base class may mean that all other classes derived from that base class must obtain some meaningless "chicken ribs". This makes the interface ambiguous. This can get into trouble for someone who inherits from that base class and has to override an abstract method. For example, a class structure is now used to represent an instrument (Instrument). Suppose we want to clear the Spit Valves of all appropriate instruments in the orchestra. One way to do this is to put a ClearSpitValve() method in the base class Instrument. But doing so creates a misconception, as it implies that there are stops in percussion and electronic instruments as well. For this situation, RTTI provides a more reasonable solution, which can put the method into a specific class (in this case, Wind, the "vent") - it is feasible to do so. But in fact a more reasonable solution is to put prepareInstrument() into the base class. Beginners often don't see this when they first start out and generally decide they have to use RTTI. Finally, RTTI can sometimes solve efficiency problems. If the code uses polymorphism a lot, but one of the objects has a problem in execution efficiency, you can use RTTI to find out that type, and then write a suitable code to improve its efficiency.

Chapter 12 Passing and Returning Objects

Chapter 14 Multithreading
When to use multithreading technology and when to avoid using it, this is an important topic we need to master. Its main purpose is to manage a large number of tasks in an orderly manner. Through the mixed use of multiple tasks, computer resources can be used more efficiently or appear more convenient to the user. The classic problem of resource leveling is how to utilize CPU during IO wait time. As for the convenience of the user, the most classic problem is how to monitor and respond sensitively to the pressing of a "stop" button during a long download process. The main disadvantages of multithreading include:
(1) When waiting to use shared resources, the running speed of the program is slowed down.
(2) Additional CPU overhead required to manage threads.
(3) Unnecessarily increased complexity, such as the stupid idea of ​​using a separate thread to update each element in the array.
(4) Multithreading symptoms such as long waits, wasteful resource competition, and deadlocks.
Another advantage of threads is that they replace "heavy" process scene switching (1000 instructions) with "light" execution switching (on the order of 100 instructions). Since all threads within a process share the same memory space, "light" scene switching only changes the program's execution and local variables. In the case of "heavy" scene switching, the change of a process requires that the memory space must be completely exchanged. Threading seems to enter a whole new field, and seems to require us to learn a whole new programming language—or at least a new set of language concepts. Since most microcomputer operating systems provide support for threads, there are also extensions to threads in programming languages ​​or libraries. In any case, programming involving threads:
(1) can be confusing at first, requiring a change in our traditional programming thinking;
(2) other languages' support for threads appears to be similar. So once you master the concept of threads, you won't have too much difficulty in other environments. Although support for threads adds somewhat to the complexity of the Java language, don't blame Java. After all, there are many good things you can do with threads.
Multiple threads may share the same resource (such as memory in an object), which is the biggest trouble when using threads. It must be ensured that multiple threads do not attempt to read and modify that resource at the same time. This requires the skillful use of the synchronized keyword. It's a useful tool, but one that has to be truly mastered because deadlocks can easily occur if not done properly. In addition, there is a very special problem to be aware of when using threads. Since Java is designed to allow us to create as many threads as we want - at least in theory (e.g. suppose to create millions of threads for an engineering finite element analysis, which is not practical for Java ). However, we generally have to control the upper limit of the number of threads we create. Because in some cases, a large number of threads will make a mess of the scene, so the work will almost come to a standstill. The critical point is not as many as thousands of objects, but below 100. Under normal circumstances, we only create a few critical threads and use them to solve a specific problem. At this time, the limitation of quantity is not a big problem. But in some of the more conventional designs, this limitation can really make us feel constrained.
Everyone should pay attention to a problem that is not very intuitive in thread processing. Due to the thread "scheduling" mechanism, by inserting a call to sleep() in the main loop of run(), you can generally make your program run faster. This makes it very demanding of programming skills, especially since longer delays seem to improve performance instead. Of course, this happens because of the short delay that may cause the "sleep() end" scheduling mechanism to be interrupted before the running thread is ready to go to "sleep". This forces the scheduling mechanism to kill it and restart it later so it can do its thing before going to sleep. One has to think a little more to realize how troublesome things really are.
One thing left out of this chapter is an example of animation, one of the most popular applications of procedural tablets these days. However, the Java JDK package provides a complete set of solutions to solve this problem (and can play sound), you can go to the demo area of ​​java.sun.com to download. In addition, we have every reason to believe that future versions of Java will provide better animation support-although the current Web has emerged many non-Java, non-programmatic animation solutions that are completely different from traditional methods. If you want to systematically study the working principle of Java animation, you can refer to the book "Core Java——Core Java", edited by Cornell&Horstmann and published by Prentice-Hall in 1997. For a more in-depth look at threading, see Concurrent Programming in Java, Doug Lea, Addison-Wiseley, 1997; or Java Threads, Oaks&Wong Edited, O'Reilly Published 1997.

Guess you like

Origin blog.csdn.net/AnalogElectronic/article/details/132335548