Không thể tạo tham chiếu tĩnh cho phương thức không tĩnh


102

Xây dựng một ứng dụng đa ngôn ngữ trong Java. Gặp lỗi khi chèn giá trị Chuỗi từ R.stringtệp tài nguyên XML:

public static final String TTT =  (String) getText(R.string.TTT);

Đây là thông báo lỗi:

Lỗi: Không thể tạo tham chiếu tĩnh đến phương thức không tĩnh getText (int) từ loại Context

Điều này gây ra như thế nào và tôi có thể giải quyết nó như thế nào?


1
Tại sao bạn cần nó phải tĩnh cho một 'ứng dụng đa ngôn ngữ'? Không hiểu lắm.
xil3

3
Không bao giờ lưu trữ tài nguyên chuỗi trong các thành viên dữ liệu tĩnh. Luôn yêu cầu họ thông qua getString()khi bạn cần. Bằng cách đó, ứng dụng của bạn sẽ điều chỉnh thích hợp để người dùng thay đổi ngôn ngữ đã chọn của họ.
CommonsWare

Câu trả lời:


143

getText()là non-static nên bạn không thể gọi nó từ một phương thức static.

Để hiểu tại sao, bạn phải hiểu sự khác biệt giữa hai điều này.

Các phương thức Instance (không tĩnh) hoạt động trên các đối tượng thuộc một kiểu cụ thể (lớp). Chúng được tạo với cái mới như thế này:

SomeClass myObject = new SomeClass();

Để gọi một phương thức thể hiện, bạn gọi nó trên instance ( myObject):

myObject.getText(...)

Tuy nhiên một phương pháp / lĩnh vực tĩnh có thể được gọi là chỉ vào loại trực tiếp, nói như thế này: Những tuyên bố trước đó là không đúng. Người ta cũng có thể tham chiếu đến các trường tĩnh với một tham chiếu đối tượng như thế myObject.staticMethod() nhưng điều này không được khuyến khích vì nó không làm rõ rằng chúng là các biến lớp.

... = SomeClass.final

Và cả hai không thể hoạt động cùng nhau khi chúng hoạt động trên các không gian dữ liệu khác nhau (dữ liệu phiên bản và dữ liệu lớp)

Hãy để tôi thử và giải thích. Hãy xem xét lớp này (mã psuedocode):

class Test {
     string somedata = "99";
     string getText() { return somedata; } 
     static string TTT = "0";
}

Bây giờ tôi có trường hợp sử dụng sau:

Test item1 = new Test();
 item1.somedata = "200";

 Test item2 = new Test();

 Test.TTT = "1";

Các giá trị là gì?

Tốt

in item1 TTT = 1 and somedata = 200
in item2 TTT = 1 and somedata = 99

Nói cách khác, TTTlà một dữ liệu được chia sẻ bởi tất cả các trường hợp của loại. Vì vậy, không có ý nghĩa gì khi nói

class Test {
         string somedata = "99";
         string getText() { return somedata; } 
  static string TTT = getText(); // error there is is no somedata at this point 
}

Vậy câu hỏi đặt ra là tại sao TTT tĩnh hoặc tại sao getText () không tĩnh?

Loại bỏ staticvà nó sẽ vượt qua lỗi này - nhưng không hiểu loại của bạn là gì, nó chỉ là một lớp thạch cao dính cho đến lỗi tiếp theo. Yêu cầu của getText()điều đó yêu cầu nó là không tĩnh là gì?


nó tĩnh vì tôi gọi nó từ một số tệp trong dự án của mình. khi tôi loại bỏ "static" thì mã lỗi đã biến mất, nhưng bây giờ tôi có rất nhiều lỗi trong các tệp khác sử dụng biến này.
Chen M

Nhưng đó là quan điểm của tôi. Bạn cần phải hiểu khi nào cả hai có thể được sử dụng.
Tăng đoàn

khi tôi thêm dòng "Hằng số thông báo_values ​​= mới Hằng số (); vào lớp hoạt động chính của tôi, nó biên dịch OK nhưng trong trình giả lập, nó bị lỗi khi hoạt động này chạy
Chen M

11

Đã có một số câu trả lời hay kèm theo lời giải thích tại sao không thể sử dụng hỗn hợp của Contextphương pháp getText()không tĩnh vớistatic final String .

Một câu hỏi hay để hỏi là: tại sao bạn muốn làm điều này? Bạn đang cố gắng tải một Stringtừ stringstài nguyên của mình và điền giá trị của nó vào một public statictrường. Tôi giả sử rằng điều này là để một số lớp khác của bạn có thể truy cập nó? Nếu vậy, không cần phải làm điều này. Thay vào đó, hãy chuyển một Contextvào các lớp khác của bạn và gọi context.getText(R.string.TTT)từ bên trong chúng.

public class NonActivity {

    public static void doStuff(Context context) {
        String TTT = context.getText(R.string.TTT);
        ...
    }
}

Và để gọi điều này từ của bạn Activity:

NonActivity.doStuff(this);

Điều này sẽ cho phép bạn truy cập String tài nguyên mà không cần sử dụng public statictrường.


1
cảm ơn bạn rất nhiều, tôi đã thay đổi tất cả các tệp theo đề xuất của bạn.
Chen M

Tôi đã cố gắng làm điều này, nhưng đối với một mảng chuỗi và với String a[] = context.getTextArray(R.array.myStringArray); ; Tuy nhiên, nó mang lại cho tôi một lỗi The method getTextArray(int) is undefined for the type Context- tại sao nó không được xác định trong khi nó hoạt động với getText?
tốt lành 99

1
@ auspicious99 đơn giản vì a Contextkhông có phương thức được gọi getTextArray, nhưng có getText. Có lẽ bạn đang nghĩ về Resourcesđiều đó cógetTextArray
dave.c

Ah, cảm ơn! Được chuyển vào Tài nguyên thay vì Ngữ cảnh (từ hoạt động đến không hoạt động) và getStringArray của tôi đã hoạt động.
tốt lành 99 ngày

9

cho những người khác tìm thấy điều này trong tìm kiếm:

Tôi thường nhận được điều này khi tôi vô tình gọi một hàm bằng cách sử dụng tên lớp thay vì tên đối tượng. Điều này thường xảy ra vì tôi đặt cho chúng những cái tên quá giống nhau: P

I E:

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

Đây rõ ràng là một phương thức tĩnh. (tốt cho điều gì đó) Nhưng điều tôi thực sự muốn làm (trong hầu hết các trường hợp là)

myclass.someFunction();

Đó là một sai lầm ngớ ngẩn, nhưng cứ sau vài tháng, tôi lại lãng phí khoảng 30 phút để lộn xộn với các biến trong định nghĩa "MyClass" để tìm ra những gì tôi đang làm sai trong khi thực sự, đó chỉ là lỗi đánh máy.

Lưu ý vui: tràn ngăn xếp làm nổi bật cú pháp để làm cho sai lầm thực sự rõ ràng ở đây.


IDE của bạn không làm nổi bật điều này? Tôi đoán bạn có thể định cấu hình nó để làm như vậy :)
Matthias Meid

2

Bạn có thể làm cho biến của mình không tĩnh

public final String TTT =  (String) getText(R.string.TTT);

hoặc đặt phương thức "getText" tĩnh (nếu có thể)


2

getText là một thành viên của Hoạt động của bạn vì vậy nó phải được gọi khi "cái này" tồn tại. Biến tĩnh của bạn được khởi tạo khi lớp của bạn được tải trước khi Hoạt động của bạn được tạo.

Vì bạn muốn biến được khởi tạo từ chuỗi Tài nguyên nên nó không thể là biến tĩnh. Nếu bạn muốn nó là tĩnh, bạn có thể khởi tạo nó với giá trị String.


2

Bạn không thể tạo tham chiếu đến biến static từ phương thức non-static. Để hiểu điều này, bạn cần hiểu sự khác biệt giữa tĩnh và không tĩnh.

Biến static là biến lớp, chúng thuộc về lớp với một thể hiện duy nhất của chúng, được tạo ở lần đầu duy nhất. Các biến không tĩnh được khởi tạo mỗi khi bạn tạo một đối tượng của lớp.

Bây giờ đến với câu hỏi của bạn, khi bạn sử dụng toán tử new (), chúng tôi sẽ tạo bản sao của mọi tệp không tĩnh cho mọi đối tượng, nhưng trường hợp này không đúng với trường tĩnh. Đó là lý do tại sao nó đưa ra lỗi thời gian biên dịch nếu bạn đang tham chiếu một biến tĩnh từ phương thức không tĩnh.


0

Câu hỏi này không mới và các câu trả lời hiện có cung cấp một số nền tảng lý thuyết tốt. Tôi chỉ muốn thêm một câu trả lời thực dụng hơn.

getText là một phương thức của lớp trừu tượng ngữ cảnh và để gọi nó, người ta cần một thể hiện của lớp con của nó (Hoạt động, Dịch vụ, Ứng dụng hoặc khác). Vấn đề là, các biến cuối cùng tĩnh công khai được khởi tạo trước khi bất kỳ phiên bản nào của Ngữ cảnh được tạo.

Có một số cách để giải quyết vấn đề này:

  1. Biến biến trở thành một biến thành viên (trường) của Activity hoặc lớp con khác của Context bằng cách loại bỏ công cụ sửa đổi tĩnh và đặt nó trong phần thân của lớp;
  2. Giữ nó tĩnh và trì hoãn việc khởi tạo đến thời điểm sau đó (ví dụ: trong phương thức onCreate);
  3. Biến nó thành một biến cục bộ ở nơi sử dụng thực tế.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.