2012-09-03 33 views
6

Tôi mới sử dụng Java. Một điều gây nhầm lẫn cho tôi là tại sao một số lớp cần new để khởi tạo và tại sao một số lớp khác KHÔNG cần new để khởi tạo.Tại sao một số lớp không cần từ "Mới" khi tạo cá thể?

Ví dụ: tôi đang xem log4j, không cần new.

Tại sao một số lớp khác lại cần mới? Ví dụ, một class Employee:

Employee X = new Employee (John); 
X.getwork(); 

vv vv

Tại sao chúng ta không nói, Logger logger = new Logger(...);? và tại sao chúng tôi có thể sử dụng nó ngay cả khi không có new, như logger.setLevel(), v.v.

+3

[Mẫu phương thức nhà máy] (http://en.wikipedia.org/wiki/Factory_method_pattern) – oldrinb

+0

'Logger.getLogger' gọi 'nhật ký mới' nội bộ. Luôn luôn có một nhà xây dựng gọi một nơi nào đó - không phải lúc nào cũng ở * mã * của bạn. – Blorgbeard

+0

WOW điều này có rất nhiều câu trả lời trong một thời gian ngắn ... – Doorknob

Trả lời

0

Trong ví dụ của bạn, bạn phải sử dụng các trường hợp khác nhau: phương thức tĩnh trả về đối tượng và lệnh gọi hàm dựng thực tế. Phương pháp tĩnh là một phương thức không cần phải gọi trên một đối tượng, đây là cơ chế bên trong có thể khởi tạo một đối tượng và trả về nó để sử dụng trong tương lai, trong phương thức này, có một lệnh gọi là "new" nhưng đối tượng có thể được cấu hình hoặc truy xuất từ ​​bộ nhớ cache trước khi trở về. Đây là loại cuộc gọi này

Logger logger = Logger.getLogger("com.foo"); 

Gọi hàm tạo thực tế (sử dụng mới) là cách thông thường để tạo đối tượng mới.

1

Logger.getLogger() trả về đối tượng Logger. new Logger() gọi hàm tạo cũng trả về một Logger. Điều này cũng loại sử dụng new quá, bởi vì bên trong lớp Logger có lẽ là một cái gì đó như:

public class Logger { 
    public static Logger getLogger() { 
     return new Logger("foo", "bar"); 
    } 
} 
0

Bạn không được về mặt kỹ thuật sử dụng các lớp Logger, nhưng đã sử dụng một phương pháp. Bạn không phải là kỹ thuật instantiating lớp Logger, cũng không giữ một tham chiếu đến nó trực tiếp như bạn làm với Logger logger = new Logger(). Thay vào đó, những gì bạn đang làm là truy cập một phương thức để lấy lại một thể hiện được trả về. Nó sẽ là tốt đẹp để xem định nghĩa lớp. Tuy nhiên, nhiều khả năng những gì bạn có là một phương thức tĩnh bên trong lớp. Và lớp học có nhiều khả năng được định nghĩa với một hàm tạo riêng. Điều này cho phép các phương thức được truy cập mà không cần khởi tạo lớp. Bạn có thể thấy một giải thích tốt về điều này và tĩnh trong java tại đây: https://stackoverflow.com/a/1844388/1026459

+0

Ông đang sử dụng lớp Logger, không chỉ gọi hàm tạo (trực tiếp). – Blorgbeard

+0

@Blorgbeard - Tôi nên nói lại điều đó. –

7

Cách duy nhất để tạo đối tượng mới trong Java là new [1]. Tuy nhiên, trong một số lớp học, bạn không được phép nói new cho chính mình, bạn phải gọi một phương thức nhà máy, có thể là tĩnh (như với ví dụ về trình ghi nhật ký của bạn) hay không. Tác giả của một lớp thiết lập điều này bằng cách làm cho (các) hàm tạo có quyền truy cập khác hơn public.

Cũng lưu ý rằng ví dụ của bạn có thể không liên quan đến một đối tượng mới. Hàm Logger có thể trả về một đối tượng cũ, không phải là đối tượng mới.

Bài thơ sau đây của Ogden Nash dường như yếu ớt liên quan:

This morning I went to the zoo 
In order to look at the gnu. 
But the old gnu was dead, 
and the new gnu, they said, 
Was too new a new gnu to view. 

[1] Trừ khi bạn tham gia vào phản xạ ở mức độ thấp, hoặc sử dụng Object.clone()

+0

Có các lựa chọn thay thế cho toán tử mới: http://stackoverflow.com/questions/95419/what-are-all-the-different-ways-to-create-an-object-in-java – maba

1

Ví dụ, một số lớp học có thể ngăn cản bạn tạo nhiều hơn một đối tượng trong ứng dụng. Đó là trường hợp bạn cần gọi một số phương thức để khởi tạo lớp, như Logger.getLogger(). GetLogger() có thể có mã như sau:

if(uniqueInstance == null) { 
    uniqueInstance = new Logger(); 
} 

return uniqueInstance; 

Trường hợp uniqueInstance là một thể hiện của Trình ghi nhật ký. Đây là một mẫu thiết kế được gọi là Singleton. Trong mẫu này, bạn không thể khởi tạo lớp vì nó là hàm tạo riêng.

Một số cách khác mà bạn không thể khởi tạo lớp là khi lớp được định nghĩa là tĩnh.

Các lớp học có công cụ xây dựng công khai và không phải là tĩnh cần được khởi tạo với từ khóa mới.

0

Một số lớp không thể được khởi tạo bên ngoài chính chúng (ví dụ: lớp Math, các lớp này có các hàm tạo không công khai). Trong số các lớp đó, một số cung cấp các phương thức trả về các cá thể của lớp (ví dụ: lớp InetAddress). Đây được gọi là phương pháp nhà máy. Chúng là các phương thức static trả lại các phiên bản của lớp mà chúng đang sử dụng, do đó, không cần sử dụng từ khóa new (thay vào đó được sử dụng bên trong các phương thức của nhà máy). Ví dụ:

public class A { 
    private A() {} 
    public A createAnA() { return new A(); } 
} 

Ở đây, createAnA() là phương pháp nhà máy.

3

Trong trường hợp này, chúng tôi đang xử lý các phương pháp nhà máy , như tôi đã nêu trong my comment.

Xem đặc điểm kỹ thuật API có liên quan trên Logger

Lấy một logger đặt tên theo các giá trị của tham số tên. Nếu logger được đặt tên đã tồn tại, thì cá thể hiện có sẽ được trả về. Nếu không, một cá thể mới sẽ được tạo.

Theo mặc định, trình ghi nhật ký không có cấp độ được đặt nhưng thừa kế nó từ tổ tiên gần nhất của chúng với cấp độ đã đặt. Đây là một trong những tính năng chính của log4j.

Các factory method pattern là một mẫu thiết kế creational, và, theo Wikipedia, thường là hữu ích trong những tình huống sau:

Các mô hình nhà máy có thể được sử dụng khi:

  • Việc tạo của một đối tượng ngăn cản việc tái sử dụng mà không cần sao chép mã đáng kể.
  • Việc tạo đối tượng yêu cầu quyền truy cập vào thông tin hoặc tài nguyên không được chứa trong lớp soạn thư.
  • Quản lý suốt đời đối tượng được tạo phải được tập trung để đảm bảo hành vi nhất quán trong ứng dụng.

Tất cả ba trong số này đều có thể áp dụng ở đây ... ai biết loại công việc nào tìm được trình ghi chính xác? Bạn không thực sự quan tâm đến việc tạo ra một logger thương hiệu mới mỗi khi bạn muốn sử dụng một ... thay vào đó, tập trung của bạn chủ yếu là chỉ - để sử dụng một.

Creative Commons Wiki cũng có một relevant article,

phương pháp Factory đôi khi được sử dụng thay cho nhà thầu đối với bất kỳ một số lý do:

  • Một số ngôn ngữ (chẳng hạn như Java) không cho phép các nhà xây dựng có tên hữu ích
  • Một số ngôn ngữ (như Java) không cho phép các nhà xây dựng có tên khác nhau (có thể cần thiết nếu bạn muốn sử dụng cùng một chữ ký phương thức cho hai nhà thầu)
  • Để cho phép cùng một ví dụ để được tái sử dụng thay vì tái tạo mỗi lần nó là cần thiết (xem FlyweightPattern)

Tôi nghĩ là lựa chọn thứ ba có lẽ là thích hợp nhất ở đây. Sử dụng tạo thủ công Logger mới, bạn không thể chia sẻ chúng một cách đầy đủ. Sử dụng mặt tiền getLogger cho phép điều này xảy ra một cách minh bạch.

Tất cả trong tất cả, việc sử dụng các phương pháp nhà máy thường cho phép mã thẳng tiến hơn mà không làm lộ công việc mà bạn không nhất thiết phải quan tâm.

1

Điều bạn đang hỏi có liên quan nhiều hơn đến các mẫu thiết kế. Lớp Logger đang theo mẫu đơn.

Giả sử bạn muốn chỉ một cá thể lớp của bạn được tạo trên ứng dụng, bạn có thể làm cho hàm tạo của bạn riêng và cung cấp phương thức tĩnh để tạo và lưu trữ đối tượng của lớp của bạn khi được gọi lần đầu tiên.

public class SingletonPattern {

 private static SingletonPattern instance; 

    private SingletonPattern(){} 

    public static synchronized SingletonPattern getInstance(){ 
     if (instance == null){ 
      instance = new SingletonPattern(); 
     } 
     return instance; 
    } 
} 

Bằng cách này bạn có thể hạn chế lớp học của bạn được khởi tạo một lần duy nhất.

Các vấn đề liên quan