【问题标题】:Type of reference type with value null?值为 null 的引用类型的类型?
【发布时间】:2011-04-19 23:13:19
【问题描述】:

根据: http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html
4.5.2 引用类型的变量
引用类型可以包含null 引用。

当赋值为null时,是否可以检索引用类型的声明类型?

具体来说,在一个使用反射的方法中,我希望该方法是空安全的,并且作用于原始声明的类型(尽管我知道下面的代码 sn-p 不起作用),例如:

String referenceType = null;
MyReflectionClass.reflectionMethod(referenceType);
...
public static void reflectionMethod(Object referenceType) {
   Class<?> declaredType = referenceType.getClass();
}

如有必要,我不会反对使用泛型将类型 T 而不是 Object 作为声明的参数类型。

编辑:我知道.getClass() 作用于实例,而不是声明的类型。我想知道是否可以向 reference 询问它的声明类型。由于类层次结构是静态的,因此获取该信息应该没有问题。

Edit2: 到这里,情况就搞清楚了:Is Java "pass-by-reference" or "pass-by-value"?
Java 只是按值传递,因此即使使用了引用类型,它也总是像传递值(对象实例)一样被处理(即使内部只传递一个对象指针)。这意味着 Java 实际上并没有知道其类型的引用类型(至少就程序员而言),它都在值实例中。
因此不可能确定任何null 值的类型。

【问题讨论】:

  • @Edit2: 说对象实例是传值是错误的。发生的情况是引用是按值传递的。
  • @brain 但是 Java 会将对该引用的任何引用(调用)处理为值。如果不是这种情况,那么 null Object 仍然是 Object 引用。它不是。 java.sun.com/docs/books/jls/third_edition/html/… 声明“引用值(通常只是引用)是指向这些对象的指针,以及一个特殊的空引用,它不引用任何对象。”链接的stackoverflow问题中的文章javadude.com/articles/passbyvalue.htm很好地解释了这一点。

标签: java null reference-type


【解决方案1】:

一句话,没有。但是,尝试查找 null 引用的成员并没有多大意义,因为 null 意味着没有任何东西。您最好只禁止 null 作为输入,可能是通过抛出 NullPointerException

如果您必须处理 null,也许最好的方法是显式传递类引用(或者更好的是,直接引用相关方法)。

public static void reflectionMethod(Object param, Class<?> referenceType) // null is dis-allowed for referenceType
{
    // ... no need to try to back-track the type from an object
}

如果你只能得到空值,那么很难(除非有其他限制,否则不可能)做得比非常幸运的猜测要好得多。

【讨论】:

  • 在这种情况下,我试图找出调用哪个方法:Class.getMethod(String, Class&lt;?&gt;...) 其中用于调用目标方法的null 参数值可能是有效的。所以在这里,这样做是有道理的。
  • 如果可以的话,直接传递类引用而不是试图从对象中回溯对象类型(参见更新的答案)
【解决方案2】:

你误会了。 getClass() 不会告诉您变量 的声明类型,它会告诉您对象 的类型(如果有的话)。让我们停下来后退一分钟——如果是这样的话,你指的是哪个变量?原始变量?方法参数?它沿途经过的任何其他变量?那将是彻底的疯狂。

【讨论】:

    【解决方案3】:

    您找不到null 引用的声明类型。泛型也无济于事,因为它们在编译时就被删除了。如果您需要知道 null 情况下的类型,则必须以某种方式在运行时传递类型。

    【讨论】:

    • 泛型并不总是在编译时被删除,但在这种情况下它们是。
    【解决方案4】:

    不,不是。在您的示例中,当您尝试在空引用 referenceType 上调用方法时,您将收到空指针异常。

    更具体地说,这是不可能的,因为在编译时不一定知道具体类型,例如如果我声明一个 Object 类型的引用并将其分配给 String,那么您的方法应该会发现该对象是 String 而不是 Object。

    Object referenceType= new String("I'm a string");
    MyReflectionClass.reflectionMethod(referenceType);
    ...
    public static void reflectionMethod(Object referenceType) {
       Class<?> declaredType = referenceType.getClass(); // returns String.class
    }
    

    【讨论】:

    • 在运行时,引用类型应该仍然知道它是String,否则它与值类型无法区分。
    • @leet3lite:String 对象知道它是一个字符串,但 Object 引用并不知道它所引用的对象是一个字符串。它只是引用任何对象。因此,如果没有对象(NULL 引用),您就无法分辨它的类型。
    • 作为一个引用类型,我希望它仍然知道它是一个字符串,但是为了使多态性起作用并允许它被作为一个对象引用,然而,这似乎不是真的(见第二次编辑)。
    • @leet3lite:它是对 String 的引用,但一旦你传入它,它就是对 Object 的引用。
    • 一个字符串是一个对象。虽然可用接口减少到 Object 可用的接口,但它仍然是一个 String。
    【解决方案5】:

    我不确定这对您的上下文是否有帮助,但您可以使用泛型来实现类似的目标 - Java 1.5+ 保留子类的类型信息。

    package spikes;
    
    import java.lang.reflect.ParameterizedType;
    
    public class ReflectMethod {
        public abstract static class GenericType<T> {
            public Class typedClass() {
                ParameterizedType pType = (ParameterizedType) getClass().getGenericSuperclass();
                return (Class) pType.getActualTypeArguments()[0];
            }
    
            public void reflectMethod(T o) {
                System.out.println("Class: " + typedClass());
            }
        }
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            GenericType<String> gs = new GenericType<String>() {
    
            };
            gs.reflectMethod("");
        }
    }
    

    【讨论】:

    • 这对空值不起作用,这是这里要问的。
    • 它适用于空值。请注意,参数用于访问类型。
    • 不幸的是,这甚至不适用于非空值。关键是我正在尝试动态获取引用类型的类型。这仅在您可以静态实例化通用 &lt;...&gt; 括号中的类型时才有效。如果我能做到这一点,那么我也可以在参数列表中静态设置类型。
    • 同意。如果您在方法调用时不知道变量的类型,这将不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 2013-07-26
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多