Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(六)之Initialization & Cleanup
Two of these safety issues are initialization and cleanup.
initialization -> bug
cleanup -> running out of resources (most notably, memory)
Java adopted the constructor, and in addition has a garbage collector that automoatically releases memory resources when they are no longer begin used.
Guaranteed initialization with the constructor
In Java, the class designer can guarantee initialization of every object by providing a constructor.
Note that the coding style of making the first letter of all methods lowercase does not apply to constructors, since the name of the constructor must match the name of the class exactly.
A constructor that takes no arguments is called the default constructor ( Java documents use the term no-arg constructor)
Constructors eliminate a large class of problems and make the code easier to read.
In Java, creation and initialization are unified concepts--you can't have one without the other.
The constructor is an unusual type of method because it has no return type. This is distinctly different from a void return value, in which the method returns nothing but you still have the option to make it return something else. Constructors return nothing and you don't have an option ( the new expression does return a reference to the newly created object, but the constructor itself has no return value.)
Method overloading
You refer to all object and methods by using names.
Well-chosen names create a system that is easier for people to understand and change.
Often, the same word expresses a number of different meanings--it's overloaded.
You don't need unique identifiers--you can deduce meaning from context.
Most programming languages require you to have a unique identifier for each method. So you could not have one method called print() for printing integers and another called print() for printing floats--each method requires a unique name.
In Java, another factor forces the overloading of method names: the constructor. Because the constructor's name is predetermined by the name of the class, there can be only one constructor name
method overloading is essential to allow the same method name to be used with different argument types (or argument list).
Distinguishing overloaded methods
How can Java know which method you mean? There's a simple rule: Each overloaded method must take a unique list of argument types
Overloading with primitives
A primitive can be automatically promoted from a smaller type to a larger one, and this can be slightly confusing in combination with overloading.
If you have a data type that is smaller than the argument in the method, that data type is promoted
char produces a slightly different effect,since if it doesn't find an exact char match, it is promoted to int.
The methods take narrower primitive values. If your argument is wider, then you must perform a narrowing conversion with a cast. If you don't do this the compiler will issue an error message.
Overloading on return values
void f() {}
int f() { return 1;}
when you call a method and ignore the return value, how can Java determine which f() should be called?
Default constructors
If you create a class that has no constructors, the compiler will automatically create a default constructor for you
However, if you define any constructors (with or without arguments), the compiler will not synthesize one for you
THe this keyword
a.peel(1);
b.peel(2);
If there's only one method called peel(), how can that method know whether it's being called for the the object a or b?
To allow you to write the code in a convenient object-oriented syntax in which you "send a message to an object," the compiler does som undercover work for you. There's a secret first argument passed to the method peel(), and that argument is the reference to the object that's being manipulated. So the two method calls become something like:
Banana.peel(a,1);
Banana.peel(b,2);
Suppose you're inside a method and you'd like to get the reference to the current object. Since that reference is passed secretly by the compiler, there's no identifier for it. However, for this purpose there's a keyword: this.
The this keyword-which can be used only inside a non-static method
以下情况需要显示指定this:
return this;
peel(this);
this.code = code;
Calling constructors from contructors
this(arg...);
In a contructor, the this keyword takes on a different meaning when you give it an argument list. It makes an explicit call to the constructor that matches that arugment list.
While you can call one constructor using this, you cannot call two.
The constructor call must be the first thing you do.
The constructor call can not from inside any method other than a constructor.
The meaning of static
Static means that there is no this for that particular method.
static are not object-oriented. However, statics are pragmatic, and there are times when you genuinely need then,so whether or not they are "proper OOP" should be left to the theoreticians.
Cleanup:finalization and garbage collection
Now consider an unusual case: Suppose your object allocates "special" memory without using new. The garbage collector only know how to release memory allocated with new, so it won't know how to release the objects's "special" memory.
To handle this case, Java provides a method called finalize() that you can define for your class.
When the garbage collector is ready to release the storage used for you object, it will first call finalize(), and only on the next garbage-collection pass will it reclaim the object's memory.
finalize()的调用时机由垃圾回收器决定,不可控。
If there is some activity that must be performed before you no longer need an object, you must perform that activity yourself. Java has no destructor or similar concept, so you must create an ordinary method to perform this cleanup.
1. Your objects might not get garbage collected.
2. Garbage collection is not destruction.
What is finalize() for
3. Garbage collection is only about memory.
So an activity that is associated with garbage collection, most notably you finalize() method, must also be only about memory and its deallocation.
The need for finalize() is limited to special cases in which your object can allocate storage in some wary other than creating an object.
It would seem that finalize() is in place because of the possibility that you'll do something Clike by allocating memory using a mechanism other than the normal one on Java.
This can happen primarily through native methods, which are a way to call non-Java code from Java. C and C++ are the only languages currently supported by native methods, but since they can call subprograms in other languages, you can effectively call anything.
C's malloc() --allocate storage
C's free() --release memory (inside your finalize())
So finalize() is not the appropriate place for normal cleanup to occur. Where should normal cleanup be performed?
You must perform cleanup
the presence of a garbage collector does not remove the need for or the utility of destructors.(And you should never call finalize() directly, so that's not a solution.) If you want som kind of cleanup performed other than storage release, you must still explicitly call an appropriate method in Java, which is the equivalent of a C++ destructor withou the convenientce.
Remember that neither garbage collection nor finalization is guaranteed. If the JVM isn't close to running out of memory, then it might not waste time recovering memory through garbage collection.
The termination condition
发现未释放资源的bug
How a garbage collector works
The trick is that the garbage collector steps in, and while it collects the garbage it compacts all the objects in the heap so that you’ve effectively moved the “heap pointer” closer to the beginning of the conveyor belt and farther away from a page fault. The garbage collector rearranges things and makes it possible for the high-speed, infinite-free-heap model to be used while allocating storage.
A simple but slow garbage-collection technique is called reference counting.
This means that each object contains a reference counter, and every time a reference is attached to that object, the reference count is increased. Every time a reference goes out of scope or is set to null, the reference count is decreased.
The garbage collectors moves through the entire list of objects, and when it finds one with a reference count of zero it releases that storage
The one drawback is that if objects circularly refer to each other they can have nonzero reference counts while still being garbage.Locating such self-referential groups requires significant extra work for the garbage collector. Reference counting is commonly used to explain one kind of garbage collection, but it doesn’t seem to be used in any JVM implementations.
In faster schemes, it is based on the idea that any non-dead object must ultimately be traceable back to a reference that lives either on the stack or in static storage. The chain might go through several layers of objects.
Thus, if you start in the stack and in the static storage area and walk through all the references, you’ll find all the live objects. For each reference that you find, you must trace into the object that it points to and then follow all the references in that object, tracing into the objects they point to, etc., until you’ve moved through the entire Web that originated with the reference on the stack or in static storage.
stop-and-copy: stop program,copy the objects from one heap to another, references be changed
inefficient reasons:
1. need two heaps , slosh all the memory back and forth between these tow separate heaps.(Some JVMs deal with this by allocating the heap in chunks as needed and simply copying from one chunk to another.)
2. Once program become stable, it might be generating little or no garbage. Despite that, a copy collector will still copy all the memory from one place to another.
mark-and-sweep: finds all live object, and mark by setting a flag in each, then sweep. So if the collector chooses to compact a fragmented heap, it does so by shuffling objects around.
For general use, mark-and-sweep is fairly slow, but when you know you’re generating little or no garbage, it’s fast.
Mark-and-sweep also requires that the program be stopped
Adaptive generational stop-and-copy mark-and-sweep
Member initialization
an uninitialized local variable is probably a programmer error, and a default value would have covered that up. Forcing the programmer to provide an initialization value is more likely to catch a bug.
If a primitive is a field in a class, however, things are a bit different. As you saw in the Everything Is an Object chapter, each primitive field of a class is guaranteed to get an initial value.
When you define an object reference inside a class without initializing it to a new object, that reference is given a special value of null.
Specifying initialization
simply to assign the value at the point you define the variable in the class.
This approach to initialization is simple and straightforward. It has the limitation that every object of the type will get these same initialization values. Sometimes this is exactly what you nedd, but at other times you need more flexibility.
Constructor initialization
There’s one thing to keep in mind, however: You aren’t precluding the automatic initialization, which happens before the constructor is entered.
//: initialization/Counter.java
public class Counter {
int i;
Counter() { i = 7; }
// ...
} ///:~
then i will first be initialized to 0, then to 7.This is true with all the primitive types and with object references, including those that are given explicit initialization at the point of definition.
Order of initialization
the variables are initialized before any methods can be called—even the constructor.
初始化顺序:
1. 父类的static属性或static代码块(按编写顺序)
2. 子类的static属性或static代码块(按编写顺序,含覆盖父类的属性)
3. 父类属性或non-static代码块(按编写顺序)
4. 父类的构造器
5. 子类属性或non-static代码块(按编写顺序)
6. 子类的构造器
Explicit static initialization
static {//...}
Non-static instance initialization
{//...}
Array initialization
int[] a; 和 int a[]; 都是有效的
int[] a1 = { 1, 2, 3, 4, 5 };
int[] a1 = new int[5];
Integer[] i = {1,2};
Integer[] ii = {1,2,};
Integer[] iii = new Integer[]{1,2,};
Variable argument lists
void printArray(Object[] args)
void printArray(Object... args) //no longer have to explicitly write out the array syntax—the compiler will actually fill it in for you when you specify varargs.You’re still getting an array, which is why print( ) is able to use foreach to iterate through the array.
printArray(new A(), new A(), new A());
printArray((Object[])new Integer[]{ 1, 2, 3, 4 }); //an array be passed to printArray( ). Clearly, the compiler sees that this is already an array and performs no conversion on it.
printArray(); //passing zero arguments is ok
You should generally only use a variable argument list on one version of an overloaded method. Or consider not doing it at all.
Enumerated types
the enum keyword, which makes your life much easier when you need to group together and use a set of enumerated types.
Because the instances of enumerated types are constants, they are in all capital letters by convention (if there are multiple words in a name, they are separated by underscores).
The compiler automatically adds useful features when you create an enum. For example, it creates a toString( ) so that you can easily display the name of an enum instance. The compiler also creates an ordinal( ) method to indicate the declaration order of a particular enum constant, and a static values( ) method that produces an array of values of the enum constants in the order that they were declared:
Although enums appear to be a new data type, the keyword only produces some compiler behavior while generating a class for the enum, so in many ways you can treat an enum as if it were any other class. In fact, enums are classes and have their own methods.
An especially nice feature is the way that enums can be used inside switch statements:
Summary
the garbage collector does add a runtime cost, the expense of which is difficult to put into perspective because of the historical slowness of Java interpreters. Although Java has had significant performance increases over time, the speed problem has taken its toll on the adoption of the language for certain types of programming problems.
Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(六)之Initialization & Cleanup的更多相关文章
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(七)之Access Control
Access control ( or implementation hiding) is about "not getting it right the first time." ...
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十三)之Strings
Immutable Strings Objects of the String class are immutable. If you examine the JDK documentation fo ...
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(二)之Introduction to Objects
The genesis of the computer revolution was a machine. The genesis of out programming languages thus ...
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十四)之Type Information
Runtime type information (RTTI) allow you to discover and use type information while a program is ru ...
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十二)之Error Handling with Exceptions
The ideal time to catch an error is at compile time, before you even try to run the program. However ...
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十一)之Holding Your Objects
To solve the general programming problem, you need to create any number of objects, anytime, anywher ...
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十)之Inner Classes
The inner class is a valuable feature because it allows you to group classes that logically belong t ...
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(九)之Interfaces
Interfaces and abstract classes provide more structured way to separate interface from implementatio ...
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(八)之Polymorphism
Polymorphism is the third essential feature of an object-oriented programming language,after data ab ...
随机推荐
- Python GUI wxPython StaticText控件背景色透明
import wx class TransparentStaticText(wx.StaticText): """ 重写StaticText控件 "" ...
- Django之模板层细说
django的模板层,基于我们前面学习的内容,也知道主要语法是{{变量相关}}{%逻辑相关%},那么具体还有哪些内容呢?且听我娓娓道来. 模板层(模板语法) 标签 过滤器 自定义标签,过滤器,incl ...
- hdu6026 dijkstra
题目链接:http://icpc.njust.edu.cn/Problem/Hdu/6026/ 题意大致是:给定一个图,要求删边使他变成树,使得每个点到0的距离就是原图中0到这个点的最短路径.其实就是 ...
- Codeforce219C-Color Stripe
E. Color Stripe time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...
- 我是如何用IDEA调试BUG的?
最近小明的bug有点多,忙的连王者荣耀都顾不上玩了,导致现在不得不抽点时间研究一下作为当前大多Java程序员开发工具的IDEA DEBUG功能,以提高效率. 一.条件断点 场景:我们在遍历某个集合,期 ...
- Leetcode——二叉树常考算法整理
二叉树常考算法整理 希望通过写下来自己学习历程的方式帮助自己加深对知识的理解,也帮助其他人更好地学习,少走弯路.也欢迎大家来给我的Github的Leetcode算法项目点star呀~~ 二叉树常考算法 ...
- 使用条件随机场模型解决文本分类问题(附Python代码)
对深度学习感兴趣,热爱Tensorflow的小伙伴,欢迎关注我们的网站!http://www.tensorflownews.com.我们的公众号:磐创AI. 一. 介绍 世界上每天都在生成数量惊人的文 ...
- coding++:java-全局异常处理
本次使用工具:SpringBoot <version>1.5.19.RELEASE</version> Code: AbstractException: package m ...
- 那些年,我们追过的java8
9月份java9就要发布了,在8月的最后一天决定回顾一下java8那些惊天动地的变化,加深理解,共同进步. 我们都知道java与c++,c不同是一个为面向对象而生的语言,面向对象思想贯彻了java发展 ...
- 3.用IntelliJ IDEA 创建Maven
一.File→New→ Project (需要下载安装配置Maven等,这些步骤省略) 二.Maven→org.apache.maven.archetypes:maven-archetype-quic ...