Java中的多态 - 我可以将对象设置为特定类型吗?

时间:2014-03-27 01:13:02

标签: java inheritance polymorphism

我是一名程序员,在长时间休息之后,他正在掌握多态性,我想知道以下是否可行。假设我有一个超类,其中有一些实例变量A,B和C.在所有子类中,A和B都是字符串,在所有子类中都是如此,但在所有子类中,C的类型可能取决于状态的子类。我想知道是否可以在超类中将C设置为'Object'类型,然后使用包装类在每个子类中指定其类型。 e.g

public class SuperClass {
    String A;
    String B;
    Object C;

    public SuperClass(){}
    }
}
public class SubClassA extends SuperClass {

    public SubClassA () {
        C = new String(); //notice this type is different from its type in the next class
    }

}

public class SubClassB extends SuperClass {

    public SubClassB () {
        C = new Integer();
    }
}

你的想法将不胜感激:) 感谢

3 个答案:

答案 0 :(得分:0)

没有。 “将对象设置为特定类型”并不意味着什么。实际上,“设置一个对象”。没有任何意义。

示例中的A,B和C不是对象,它们是变量。 Java中有三种变量;基元(例如,int,boolean,double),数组引用变量和对象引用变量。 A,B和C是对象引用变量。这意味着,A,B和C各自拥有某个对象的身份

最初,它们都持有null,这是一个特殊的对象引用,意思是“没有对象。”

您的子类构造函数每个都创建一个新对象,并将其标识存储在C。

对象具有可在运行时获知的类型,并且变量具有仅在编译时已知的类型。如果代码可以证明您将某个对象的标识分配给具有不兼容类型的对象引用变量,则编译器将拒绝您的代码。

变量C的类型Object与任何对象兼容。您可以为其指定String引用,也可以为其分配Integer引用,或者可以为其分配ForkJoinPool.ForkJoinWorkerThreadFactory引用。缺点是,编译器只允许您通过C执行操作,可以对每种类型的对象执行操作。编译器不允许你调用C.toUpperCase()---即使它持有对实际String对象的引用也不会.---因为你已经明确声明C 可以持有引用 not Strings。


我不会写你写的代码,但很难说我会写什么代替,因为你的例子实际上并没有任何东西。如果您提出有关如何解决实际问题的问题,您将在此论坛中获得更好的答案。

答案 1 :(得分:0)

首先要了解对象引用之间的区别。 对象是您使用new创建的,它具有从创建时起固定的特定类型(类)。 引用是"指针"对象。

单个引用可以指向不同时间的不同类型的对象,只要引用的声明类型是对象或其超类的类。 Object是所有对象的超类(包括数组,但不是"标量"如intcharfloat等,因此是参考声明类型Object可以指向任何对象。

当然,如果您将引用声明为Object,那么即使您(据称)知道其中的内容,编译器和JVM也无法提供线索。所以你需要"演员"在使用它之前引用适当的类型。例如,知道您之前已将指向String对象的指针存储到C中,您可能会这样做:

String castFromC = (String)C;
Char charFromC = castFromC.charAt(5);

如果事实证明C不是字符串而是整数字,那么(String)"演员"操作将在运行时因ClassCastException而失败。

答案 2 :(得分:0)

根据我对您的疑虑的理解,您发布的代码对我来说很合适。但是,它会强制您将C转换为特定类型,以使其成为可操作的"因为您刚刚将对象引用C声明为指向Object类型的Java对象"的引用。

为了避免丑陋的类型转换,你可以像这样生成你的超类

class SuperClass<T> {
    String A;
    String B;
    T C;

    public SuperClass(){}
}

在您的子类中,您可以像这样使用它

class SubClassA extends SuperClass<String> {

    public SubClassA () {
        C = new String();
    }
}

class SubClassB extends SuperClass<Integer> {

    public SubClassB () {
        C = new Integer(0);
    }
}

此外,一个惯例是你的实例变量应该有一个有意义的名字,以小写开头,声明为private,并暴露给其他带有公共getter和setter的类。