Một số người đã hỏi: làm thế nào singleton có thể trả về một con trỏ null?
Tôi đang trả lời câu hỏi đó. (Tôi không thể trả lời trong một bình luận vì tôi cần đăng mã.)
Nó có thể trả về null ở giữa hai sự kiện: (1) lớp được tải và (2) đối tượng của lớp này được tạo. Đây là một ví dụ:
class X {
static X xinstance;
static Y yinstance = Y.yinstance;
X() {xinstance=this;}
}
class Y {
static X xinstance = X.xinstance;
static Y yinstance;
Y() {yinstance=this;}
}
public class A {
public static void main(String[] p) {
X x = new X();
Y y = new Y();
System.out.println("x:"+X.xinstance+" y:"+Y.yinstance);
System.out.println("x:"+Y.xinstance+" y:"+X.yinstance);
}
}
Hãy chạy mã:
$ javac A.java
$ java A
x:X@a63599 y:Y@9036e
x:null y:null
Dòng thứ hai cho thấy Y.xinstance và X.yinstance là null ; chúng là null vì các biến X.xinstance ans Y.yinstance đã được đọc khi chúng là null.
Điều này có thể được sửa chữa? Đúng,
class X {
static Y y = Y.getInstance();
static X theinstance;
static X getInstance() {if(theinstance==null) {theinstance = new X();} return theinstance;}
}
class Y {
static X x = X.getInstance();
static Y theinstance;
static Y getInstance() {if(theinstance==null) {theinstance = new Y();} return theinstance;}
}
public class A {
public static void main(String[] p) {
System.out.println("x:"+X.getInstance()+" y:"+Y.getInstance());
System.out.println("x:"+Y.x+" y:"+X.y);
}
}
và mã này cho thấy không có bất thường:
$ javac A.java
$ java A
x:X@1c059f6 y:Y@152506e
x:X@1c059f6 y:Y@152506e
NHƯNG đây không phải là một tùy chọn cho Application
đối tượng Android : lập trình viên không kiểm soát thời gian khi nó được tạo.
Một lần nữa: sự khác biệt giữa ví dụ thứ nhất và ví dụ thứ hai là ví dụ thứ hai tạo ra một thể hiện nếu con trỏ tĩnh là null. Tuy nhiên, một lập trình viên không thể tạo các đối tượng ứng dụng Android trước khi hệ thống quyết định làm điều đó.
CẬP NHẬT
Thêm một ví dụ khó hiểu khi các trường tĩnh khởi tạo xảy ra null
.
Main.java :
enum MyEnum {
FIRST,SECOND;
private static String prefix="<", suffix=">";
String myName;
MyEnum() {
myName = makeMyName();
}
String makeMyName() {
return prefix + name() + suffix;
}
String getMyName() {
return myName;
}
}
public class Main {
public static void main(String args[]) {
System.out.println("first: "+MyEnum.FIRST+" second: "+MyEnum.SECOND);
System.out.println("first: "+MyEnum.FIRST.makeMyName()+" second: "+MyEnum.SECOND.makeMyName());
System.out.println("first: "+MyEnum.FIRST.getMyName()+" second: "+MyEnum.SECOND.getMyName());
}
}
Và bạn nhận được:
$ javac Main.java
$ java Main
first: FIRST second: SECOND
first: <FIRST> second: <SECOND>
first: nullFIRSTnull second: nullSECONDnull
Lưu ý rằng bạn không thể di chuyển khai báo biến tĩnh một dòng trên, mã sẽ không biên dịch.
<application>
nút của tệp AndroidManifest.xml để bao gồm định nghĩa thuộc tính sau :android:name="MyApp"
. MyApp cần phải nằm trong cùng gói mà tài liệu tham khảo của bạn.