2008-11-14 41 views
171

Lỗi người mới bắt đầu rất phổ biến là khi bạn cố gắng sử dụng một thuộc tính lớp "tĩnh" mà không tạo một cá thể của lớp đó. Nó để lại cho bạn thông báo lỗi được đề cập:Lý do đằng sau "phương pháp không tĩnh không thể được tham chiếu từ ngữ cảnh tĩnh" là gì?

Bạn có thể đặt phương thức tĩnh tĩnh hoặc tạo một thể hiện của lớp đó để sử dụng các thuộc tính của nó.

Tại sao? Tôi không yêu cầu giải pháp. Tôi sẽ biết ơn vì biết lý do đằng sau nó là gì. Lý do chính yếu!

private java.util.List<String> someMethod(){ 
    /* Some Code */ 
    return someList;    
} 

public static void main(String[] strArgs){   
    // The following statement causes the error. You know why.. 
    java.util.List<String> someList = someMethod();   
} 

Trả lời

253

Bạn không thể gọi thứ gì đó không tồn tại. Vì bạn chưa tạo một đối tượng, phương thức tĩnh chưa tồn tại. Một phương thức tĩnh (theo định nghĩa) luôn tồn tại.

+3

"Vì bạn chưa tạo một đối tượng, phương pháp không tĩnh chưa tồn tại." - Cảm ơn rất nhiều. Tôi nên nghĩ về nó. – DragonBorn

+5

Phương thức tự tồn tại. Đâu đó trong định nghĩa lớp đã tải. Vì vậy, câu trả lời là sai :) –

+28

@Vladimir, OK nếu bạn muốn được cầu kỳ. :) "không tồn tại trong ngữ cảnh hiện tại" :) –

41

Phương pháp bạn đang cố gắng gọi là phương pháp mức thể hiện; bạn không có một ví dụ.

static phương pháp thuộc lớp, không phải là static phương pháp thuộc về các phiên bản của lớp học.

+0

"phương pháp không tĩnh thuộc về các phiên bản của lớp" - Câu trả lời. Nhưng tại sao nó thuộc về trường hợp của lớp? Cảm ơn bạn. – DragonBorn

+9

@ZiG: bởi vì bạn đã nói với nó bằng cách không đánh dấu nó tĩnh –

+1

Đối với các nhà phát triển mới bắt đầu, tôi đã tạo một ví dụ để hiểu những gì @ StevenA.Lowe đề cập ở trên. https://repl.it/repls/WavyNeighboringSpotteddolphin – supritshah1289

1

Phương pháp tĩnh liên quan đến một hành động đối với một loại đối tượng, trong khi phương thức tĩnh không liên quan đến một hành động đối với một thể hiện của kiểu đối tượng đó. Thông thường nó là một phương thức thực hiện một cái gì đó có liên quan đến cá thể.

Ex:

lớp Car có thể có một phương pháp rửa, mà sẽ chỉ rửa một chiếc xe đặc biệt, trong khi một phương pháp tĩnh sẽ áp dụng cho các loại xe.

+0

Không phải tất cả các phương pháp đều có tác dụng phụ! Không phải là một hành động * đối với *, nó cũng có thể là thứ mà đối tượng nói với bạn. – Hugo

1

nếu một phương thức không tĩnh, nghĩa là "cho" trình biên dịch biết rằng phương thức này yêu cầu quyền truy cập vào dữ liệu mức cá thể trong lớp, (như trường không tĩnh). Dữ liệu này sẽ không có sẵn trừ khi một thể hiện của lớp đã được tạo ra. Vì vậy, trình biên dịch ném một lỗi nếu bạn cố gắng gọi phương thức từ một phương thức tĩnh .. Nếu trong thực tế, phương thức này KHÔNG tham chiếu đến bất kỳ thành phần không tĩnh nào của lớp, làm cho phương thức tĩnh.

Trong Resharper, ví dụ, chỉ cần tạo ra một phương pháp không tĩnh mà không tham chiếu tới bất kỳ thành viên tĩnh của lớp tạo ra một thông điệp cảnh báo "Phương pháp này có thể được thực hiện tĩnh"

4

Những câu trả lời cho đến nay mô tả tại sao, nhưng đây là một cái gì khác bạn có thể muốn xem xét:

bạn có thể có thể gọi một phương thức từ một lớp instantiable bằng cách thêm một lời gọi phương thức khởi dựng của nó,

Object instance = new Constuctor().methodCall(); 

hoặc

primitive name = new Constuctor().methodCall(); 

Điều này rất hữu ích, bạn chỉ muốn sử dụng một phương thức của lớp có thể nhanh chóng một lần trong một phạm vi duy nhất. Nếu bạn đang gọi nhiều phương thức từ một lớp instantiable trong một phạm vi duy nhất, chắc chắn tạo một thể hiện có thể tham chiếu.

10

Tôi vừa mới nhận ra, tôi nghĩ mọi người không nên tiếp xúc với khái niệm "tĩnh" rất sớm.

Phương pháp tĩnh có thể là ngoại lệ thay vì chỉ tiêu. Đặc biệt là sớm trên anyways nếu bạn muốn tìm hiểu OOP. (Tại sao bắt đầu với ngoại lệ cho quy tắc?) Điều đó rất chống lại sư phạm của Java, rằng điều "đầu tiên" bạn nên học là public static void chính điều. (Rất ít ứng dụng Java thực sự có phương thức chính của riêng mình.)

+0

Tôi đã gặp phải vấn đề này với lỗi được đề cập ở trên, nhưng phải học cách sử dụng tĩnh để sử dụng một thể hiện của một lớp trên các hoạt động khác nhau, vì vậy tôi đang gặp khó khăn với nó. :(cố gắng rất nhiều thứ, nhưng không hoạt động. – Azurespot

2

Trình biên dịch thực sự thêm đối số vào các phương thức không tĩnh. Nó thêm một this pointer/reference. This is also the reason why a static method can not use this, bởi vì không có đối tượng.

16

Bản chất của lập trình hướng đối tượng là gói gọn logic cùng với dữ liệu mà nó hoạt động.

Phương pháp thể hiện là logic, các trường mẫu là dữ liệu. Cùng nhau, chúng tạo thành một vật thể.

public class Foo 
{ 
    private String foo; 
    public Foo(String foo){ this.foo = foo; } 
    public getFoo(){ return this.foo; } 

    public static void main(String[] args){ 
     System.out.println(getFoo()); 
    } 
} 

Điều gì có thể là kết quả của việc chạy chương trình trên?

Không có đối tượng, không có dữ liệu cá thể và trong khi các phương thức thể hiện tồn tại như một phần của định nghĩa lớp, chúng cần một cá thể đối tượng để cung cấp dữ liệu cho chúng.

Về lý thuyết, một phương pháp thể hiện không truy cập bất kỳ dữ liệu cá thể nào có thể hoạt động trong ngữ cảnh tĩnh, nhưng sau đó không có lý do nào để nó trở thành một phương thức thể hiện. Đó là một quyết định thiết kế ngôn ngữ để cho phép nó anyway thay vì tạo ra một quy tắc bổ sung để cấm nó.

+0

câu trả lời hay nhất –

0

Lý do đơn giản đằng sau điều này là các thành viên dữ liệu tĩnh của lớp cha có thể được truy cập (chỉ khi chúng không bị ghi đè), ví dụ (không tĩnh) thành viên dữ liệu hoặc phương pháp chúng tôi cần tham chiếu của họ và để họ có thể chỉ được gọi thông qua một đối tượng.

10

Tôi nghĩ rằng nó là giá trị chỉ ra rằng bởi các quy tắc của ngôn ngữ Java trình biên dịch Java chèn tương đương với "này". khi nó thông báo rằng bạn đang truy cập các phương thức instance hoặc các instance fields mà không có một cá thể rõ ràng. Tất nhiên, trình biên dịch biết rằng nó chỉ có thể làm điều này từ bên trong một phương thức thể hiện, có một biến "this", như các phương thức tĩnh không.

Có nghĩa là khi bạn đang ở trong một phương pháp dụ sau đây là tương đương:

instanceMethod(); 
this.instanceMethod(); 

và đây cũng là tương đương: "này"

... = instanceField; 
... = this.instanceField; 

Trình biên dịch được một cách hiệu quả chèn khi bạn không cung cấp một trường hợp cụ thể.

Điều này có thể gây nhầm lẫn cho người mới: nó có nghĩa là các cuộc gọi và cuộc gọi tĩnh đôi khi có cùng cú pháp trong khi thực tế là các cuộc gọi của các kiểu khác nhau và cơ chế cơ bản.

Cuộc gọi phương thức thể hiện đôi khi được gọi là lời gọi phương thức hoặc công văn vì các hành vi của các phương thức ảo hỗ trợ đa hình; hành vi gửi đi xảy ra bất kể bạn đã viết một cá thể đối tượng rõ ràng để sử dụng hay trình biên dịch đã chèn một "this".

Cơ chế gọi phương thức tĩnh đơn giản hơn, giống như cuộc gọi hàm bằng ngôn ngữ không phải là OOP.

Cá nhân, tôi cho rằng thông báo lỗi là gây hiểu nhầm, có thể đọc "phương pháp không tĩnh không thể được tham chiếu từ ngữ cảnh tĩnh mà không chỉ định đối tượng rõ ràng".


Trình biên dịch phàn nàn là không thể đơn giản chèn tiêu chuẩn "này". như trong các phương thức instance, bởi vì đoạn mã này nằm trong một phương thức tĩnh; tuy nhiên, có lẽ tác giả chỉ quên cung cấp cá thể quan tâm cho lời gọi này — nói, một cá thể có thể được cung cấp cho phương thức tĩnh làm tham số hoặc được tạo trong phương thức tĩnh này.

Tóm lại, bạn chắc chắn nhất có thể gọi các phương thức ví dụ từ bên trong một phương thức tĩnh, bạn chỉ cần có và chỉ định một đối tượng cá thể rõ ràng cho lời gọi.

2

Nếu chúng ta cố gắng truy cập một phương thức thể hiện từ ngữ cảnh tĩnh, trình biên dịch không có cách nào để đoán phương thức thể hiện nào (biến cho đối tượng nào), bạn đang đề cập đến. Mặc dù, bạn luôn có thể truy cập nó bằng cách sử dụng một tham chiếu đối tượng.

0

Vì vậy, bạn đang yêu cầu một lý do chính yếu?

Vâng, vì bạn đang phát triển trong Java, trình biên dịch tạo ra một mã đối tượng mà Máy ảo Java có thể giải thích. Tuy nhiên, JVM là một chương trình nhị phân chạy bằng ngôn ngữ máy (có thể là phiên bản JVM dành riêng cho hệ điều hành và phần cứng của bạn trước đây được biên dịch bởi một ngôn ngữ lập trình khác như C để lấy mã máy có thể chạy trong bộ xử lý của bạn). Cuối cùng, bất kỳ mã nào cũng được dịch sang mã máy. Vì vậy, tạo một đối tượng (một thể hiện của một lớp) tương đương với dự trữ một không gian bộ nhớ (bộ nhớ đăng ký sẽ là bộ xử lý đăng ký khi bộ lập lịch CPU của hệ điều hành đặt chương trình của bạn ở đầu hàng đợi để thực thi nó) để có một nơi lưu trữ dữ liệu có thể đọc và ghi dữ liệu. Nếu bạn không có một thể hiện của một lớp (điều này xảy ra trên một ngữ cảnh tĩnh), thì bạn không có bộ nhớ đó để đọc hoặc ghi dữ liệu. Trong thực tế, giống như những người khác đã nói, dữ liệu không tồn tại (bởi vì từ khi bắt đầu bạn chưa bao giờ viết không dành riêng bộ nhớ để lưu trữ nó).

Xin lỗi vì tiếng anh của tôi! Tôi là latin!

0

Phương pháp không tĩnh phụ thuộc vào đối tượng. Nó được công nhận bởi chương trình khi đối tượng được tạo ra.

Phương pháp tĩnh có thể được gọi ngay cả trước khi tạo đối tượng. Các phương thức tĩnh là rất tốt cho việc so sánh hoặc các hoạt động không phụ thuộc vào các đối tượng thực tế mà bạn dự định làm việc.

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