Nhận lớp theo tên của nó


81

Nếu tôi có một lớp Activity được gọi là TestActivity trong ứng dụng của mình, có cách nào để lấy lớp của nó theo tên của nó như trong ví dụ này không:

Class<?> c = getClassByName("TestActivity");

Câu trả lời:


158

sử dụng forName để thay thế ..

một cái gì đó như thế này ..

 try {
    Class<?> act = Class.forName("com.bla.TestActivity");
 } catch (ClassNotFoundException e) {
        e.printStackTrace();
}

30
Bạn cũng phải cung cấp tên gói hoàn chỉnh. ví dụ: com.bla.TestActivity làm đối số cho Class.forName
Richie

1
Bạn cũng có thể làm gì đó để nhận được Class<? extends SomeClass>?
Gobliins

@Gobliins Không - trình biên dịch không thể đảm bảo bạn sẽ nhận được loại lớp nào, vì vậy nó cung cấp cho bạn một Lớp <?>. Nếu bạn biết loại lớp bạn sẽ nhận được, bạn sẽ phải cast nó (thậm chí bạn vẫn nhận được cảnh báo cast không được chọn vì quá trình cast không an toàn).
Dylanthepiguy

@Gobliins Hãy xem câu trả lời của tôi về cách lấy một lớp con của một loại nhất định.
raphinesse

6

Bạn có thể sử dụng Class::forNameđể lấy một đối tượng lớp không xác định. Nếu bạn muốn nhận một lớp đã nhập, bạn có thể sử dụng Class::asSubclasslớp được trả về bởi Class::forName:

Class<? extends Activity> activityClass = Class.forName("com.example.TestActivity")
                                               .asSubclass(Activity.class);

Tất nhiên bạn cũng sẽ phải xử lý một loạt các loại ngoại lệ khác nhau. Như thường lệ khi xử lý phản ánh.


6

Các Class.forName dường như có trường hợp ngoại lệ trên đó. Đây chỉ là mở rộng ở trên để giải quyết vấn đề này.

try { t = Class.forName("com.package.classname"); } catch (Exception ignored){}

Cách thông thường trên SO để trả lời như thế này là chỉnh sửa câu trả lời của họ. Mặc dù vì các ngoại lệ rất nhiều trong Java (và mã của bạn chỉ cần bỏ qua nó), một nhận xét sẽ đủ để giải quyết vấn đề đó.
crazyhatfish

7
@crazyhatfish - Có vẻ như Patrick có thể không có đặc quyền để làm bất cứ điều gì hữu ích ngoại trừ đăng câu trả lời của riêng anh ấy.
amess

3
@amess Rất tiếc, quyền của bạn, tôi quên nhận xét cần đại diện. Cảm ơn vì đã sửa tôi.
crazyhatfish

2

Tôi cũng có một yêu cầu tương tự, tôi có một json đến từ phần phụ trợ có chứa màn hình và ánh xạ hoạt động. Vì json chung cho cả iOS / Android, chúng tôi không thể thêm các thuật ngữ như Activityjson, vì vậy đây là những gì chúng tôi đã làm

  1. Trong json cho tất cả Activityhoặc Viewcontrollers, sử dụng các tên đơn giản, nghĩa là cho HomeActivityHomeViewControllerchúng tôi sẽ sử dụng "Home" trong json

  2. Trong ứng dụng, chúng tôi phân tích cú pháp json và tôi đã viết các phương thức tiện ích bên dưới để nhận hoạt động một cách linh hoạt

Để lấy tên của lớp (tức là nếu chúng ta vượt qua Trang chủ, chúng ta sẽ quay lại com.package.HomeActivity)

    fun getClassInfoFor(name: String, context: Context):String{
        var str = "${context.getPackageName()}.${name}Activity"
        return str
    }

Bây giờ để lấy lớp từ chuỗi

        try {
            val className = Utilties.getClassInfoFor(activityNameFromJSON, context)
            val fetchedClass = Class.forName(className)
            val showDetailsIntent = Intent(context, fetchedClass)
            context.startActivity(showDetailsIntent)
        } catch (e: ClassNotFoundException) {
            e.printStackTrace()
        }

Bằng cách này, tôi có thể dễ dàng quản lý nhiều lớp với cùng một phương pháp. Tôi sử dụng điều này trong chế độ xem tái chế, nơi mọi tế bào của tôi điều hướng đến một hoạt động khác nhau.


Xin lưu ý rằng câu trả lời của bạn là trong Kotlin;) Có thể thay đổi nó một chút để biến nó thành Java?
LMD

@LMD có lẽ hầu hết các nhà phát triển Android tìm kiếm một phiên bản Kotlin câu trả lời cần thiết, không phải java;)
Ruslan Berozov

@RuslanBerozov op đã gắn thẻ câu hỏi là [java] vì vậy tôi mong đợi ít nhất một phiên bản Java (tất nhiên là Kotlin bổ sung cũng tốt).
LMD

@LMD xin lỗi, nhưng op đã đăng một câu hỏi vào năm 2012. Thực sự khó tưởng tượng rằng anh ấy biết về Kotlin vào thời điểm đó. Vấn đề là câu hỏi đó cũng được đánh dấu là [android], và ngày nay tôi mong đợi phiên bản Kotlin hơn.
Ruslan Berozov

-2

Nó có thể không phải là câu trả lời phù hợp nhất cho câu hỏi của bạn, nhưng nói chung là không tốt cho các ký tự tên lớp hardcode dưới dạng chuỗi. Nó có thể tốt hơn để sử dụng

Class<?> act = TestActivity.class;

cú pháp.

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.