简体   繁体   English

无论如何在java中在运行时更改对象类?

[英]Is there anyway to change object class at runtime in java?

My code kind of look like this.我的代码看起来像这样。

class A {
 //constructor
}

class B extends A {
 //constructor

 public void someMethod() {
  System.out.println("In B");
 }
}

class C extends A {
 //constructor

 public void someMethod() {
  System.out.println("In C");
 }
}

public static void main(String args[]){
 Object obj = new obj();
 B[] classB = new B(){0,1,2,3,4};
 C[] classC = new C(){0,1,2,3,4};

 Scanner input = new Scanner(System.in);

 System.out.print("Enter class: ");

 String class = input.next();

 System.out.print("Enter index: ");

 int index = input.nextInt();

 if(class.equals("B") {

// I want to change Object type of obj to B so that I can access methods of B // 我想把obj的Object类型改成B,这样我就可以访问B的方法了

 obj = classB[index];

 } else if(class.equals("C")  {

// I want to change Object type of obj to C so that I can access methods of C // 我想把obj的Object类型改成C,这样我就可以访问C的方法了

  obj = classC[index];
 }

// if user input class B the code below should run method of class B // 如果用户输入类 B 下面的代码应该运行类 B 的方法

 obj.someMethod();
}

I have searched for something along the lines of permanent casting of object but it was too complicated for me.我一直在寻找类似于永久铸造物体的东西,但对我来说太复杂了。

You appear to be confusing a variable type and the type of the object it is pointing at.您似乎混淆了变量类型和它指向的对象的类型。

Given:鉴于:

class Parent {}
class Child extends Parent {}

In:在:

Parent p = new Child();

You have exactly 1 instance;你正好有 1 个实例; its type is Child ;它的类型是Child like anything whose type is Child , it is also of type Parent , and also of type Object .就像任何类型为Child东西一样,它也是Parent类型,也是Object类型。

It is confusing to say that 'p is of type Parent'.说“p 是 Parent 类型”令人困惑。 So don't say it.所以别说了。

This works: p is a variable of type Parent;这是有效的:p 是 Parent 类型的变量; it is referencing an instance of Child.它正在引用 Child 的一个实例。

And should clarify a thing or two.并且应该澄清一两件事。

p can point at other things. p 可以指向其他东西。 You can write:你可以写:

Parent p;
p = null;
p = new Child();
p = new Parent();

and the compiler won't complain.并且编译器不会抱怨。 Over the lifetime of p, it starts out being illegal to read from it, then referencing nothing (null), then referencing an instance of Child, and finally referencing an instance of Parent.在 p 的生命周期中,从它读取开始是非法的,然后不引用任何内容(空),然后引用 Child 的实例,最后引用 Parent 的实例。 No, you can't 're-define' the p variable to all of a sudden be of type Child, even if it is pointing at an object which so happens to actually be a child.不,您不能突然将 p 变量“重新定义”为 Child 类型,即使它指向的对象恰好是一个孩子。 That's a bit like trying to redefine a circle to have corners.这有点像试图重新定义一个圆以获得角点。

Nevertheless, in:尽管如此,在:

Parent p = new Child();

p (the variable) is of type Parent, but p (after resolving the reference) is a Child. p(变量)是 Parent 类型,但 p(解析引用后)是 Child 类型。 You can treat it as one:你可以把它当作一个:

Child c = (Child) p;

This is a type-checking cast operation: This code can do one of two things:这是一个类型检查转换操作:这段代码可以做两件事之一:

  1. If the p variable so happens to be referencing either nothing (null) or an instance of Child or any subtype thereof, then this code does absolutely nothing whatsoever;如果 p 变量碰巧没有引用(null)或 Child 的实例或其任何子类型,那么这段代码绝对不做任何事情; it's just c = p , and the cast operation serves solely to make the compiler do it (without the cast, the compiler will refuse to compile this).它只是c = p ,并且强制转换操作仅用于使编译器执行此操作(没有强制转换,编译器将拒绝编译它)。 The point is, nothing is converted , p references an object, and after this statement, c references the exact same object.关键是,什么都没有被转换,p 引用了一个对象,在这条语句之后,c 引用了完全相同的对象。 It's just that you can do more with the c variable now.只是你现在可以用 c 变量做更多的事情。 But it's the same instance.但这是同一个例子。
  2. If the p variable happens to be referencing anything else, a ClassCastException is thrown.如果 p 变量恰好引用了其他任何内容,则会抛出ClassCastException

In no case is anything converted, and the cast operation cannot convert anything at all ever, except for primitives (that's a real guns and grandmas situation: int x = (int) v; looks very similar to String y = (String) z; but these 2 snippets do completely unrelated things that just happen to look similar.在任何情况下都不会转换任何内容,并且强制转换操作根本无法转换任何内容,除了原语(这是真正的枪和奶奶的情况: int x = (int) v;看起来非常类似于String y = (String) z;但这 2 个片段做了完全不相关的事情,只是碰巧看起来很相似。

Change the line换线

Object obj = new Object();

in your code to在你的代码中

A obj;

Also correct your class A to:还将您的 A 类更正为:

abstract class A {
   //constructor
   public abstract void someMethod();
}

and your code will work (as explained by @rzwitserloot).并且您的代码将起作用(如@rzwitserloot 所述)。


On the other side, if you don't want to define the method in class A, you must cast your obj to the correct type before you can call the method: leave your code as it is, but replace your line at the end:另一方面,如果您不想在类 A 中定义方法,则必须先将 obj 转换为正确的类型,然后才能调用该方法:保持代码不变,但在最后替换您的行:

obj.someMethod();

with:和:

if (obj instanceof B) {
   ((B)obj).someMethod();
}
else if (obj instanceof C) {
   ((C)obj).someMethod();
}
else {
   // throw some error
}

But the best way is to just define an interface (I suggest "ClassNameReporter") with the method someMethod() and let class B and C implement it.但最好的方法是使用 someMethod() 方法定义一个接口(我建议使用“ClassNameReporter”),然后让类 B 和 C 实现它。 Then you can keep your code as it is except changing然后你可以保留你的代码,除了改变

Object obj = new Object();

in your code to在你的代码中

ClassNameReporter obj;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM