Trong Java, tôi nạp lớp bên ngoài (trong file .jar) bằng cách này:Scala - đối tượng Dynamic/lớp bốc
ClassLoader classLoader = new URLClassLoader(new URL[] {
new File("module.jar").toURI().toURL()});
Class clazz = classLoader.loadClass("my.class.name");
Object instance = clazz.newInstance();
//check and cast to an interface, then use it
if (instance instanceof MyInterface)
...
Và nó hoạt động tốt.
====================
Bây giờ tôi muốn làm điều tương tự trong Scala. Tôi có một trait
tên Module
(Module.scala
):
trait Module {
def name: String
}
object Module {
lazy val ModuleClassName = "my.module.ExModule"
}
tôi viết một module mở rộng Module
, sau đó biên dịch nó để module.jar
:
package my.module
import Module
object ExModule extends Module {}
Sau đó, tôi tải nó bằng mã này:
var classLoader = new URLClassLoader(Array[URL](
new File("module.jar").toURI.toURL))
var clazz = classLoader.loadClass(Module.ModuleClassName)
Nó hoạt động tốt. Nhưng nếu tôi có thể tạo thể hiện mới, tôi nhận được ngoại lệ này:
java.lang.InstantiationException: my.module.ExModule
Nếu tôi thử nghiệm nó:
-> luôn luôn trả false
.
Bạn có thể giúp tôi về vấn đề này không?
Edited
Tôi đoán đó là vì ExModule
là một object
(không class
). Nhưng khi tôi thay đổi nó thành class
và classLoader.loadClass(...)
tăng số java.lang.NoClassDefFoundError
. Tôi đoán đó là vì ExModule
được mở rộng từ một số trait
.
Tôi đang bối rối. Có ai giúp tôi không?
Edited
clazz.isInstanceOf[Class[Module]]//or Class[Byte], or Class[_]...
lợi nhuận true
.
Tôi nghĩ rằng bạn đã gần gũi hơn với việc biến nó thành một lớp (khi bạn nhận được ClassNotFoundException). Bạn có chắc chắn rằng khi bạn tham chiếu module.jar bạn đang nhận được đường dẫn phải không? Thực tế là nó được mở rộng từ một đặc điểm không nên tạo ra bất kỳ sự khác biệt nào - ExModule là một lớp (trong trường hợp đó). –
Có, tôi chắc chắn đường dẫn đến 'module.jar' là chính xác. Phương thức 'classLoader.loadClass (...)' hoạt động tốt (trong trường hợp 'ExModule' là' đối tượng'). –
Bạn có thể xem mã bytecode được biên dịch (thông qua javap hoặc tương tự) không? Scalac có thói quen vui nhộn khi thêm $ s và các tên lạ khác xung quanh địa điểm, và có lẽ ExModule của bạn chỉ có một chút tên khác trong phiên bản đã biên dịch. Ngoài ra, bạn có thể yêu cầu scalac để in mã java bằng scala của bạn (Tôi chỉ không nhớ tùy chọn bây giờ). – Rogach