简体   繁体   中英

Issue casting with .class in Java 8?

I thought that.class was the class of the object it was being called on. However this does not fit with what I was trying to do with a program. I'll give some examples.

//o is of type Object
//this method throws error "cannot find symbol" for the cast method
SampleClass.cast(o);
//sampleClass is an instance of SampleClass
//this method throws error "<identifier> expected"
sampleClass.class.cast(o);
//this method works!
SampleClass.class.cast(o);
//this returns two "<identifier> expected" errors
sampleClass.class.class.cast(o);
//this works too!
((SampleClass) o)

I previously thought that sampleClass.class == SampleClass, an object of type Class. I also thought that SampleClass.class would return something really meta that's hard to think about. Now I know that I don't really know anything. Any help solving this conundrum is appreciated:)

Edit: Thanks everyone. I'm happy to be learning this about Java. I'm grateful for the help

I have put together some compilable Java code that can maybe clarify some usage of Class and casting. Hopefully it is self-documenting enough.

You can think of Sample.class as a "class literal" in the same way "something" is a string literal. It is an expression, it has a value, it is assignable to a variable, it is an object. The type of this object is Class<Sample> . On the other hand Sample is a type, not an expression, you cannot assign it to a variable.

Class is a meta-class, ie it is a class which desribes another class. You cannot go more meta than Class<Class> classClass = Class.class; . Interesting thing: there are also primitive class literals like int.class .

class Main {
    public static void main(String[] args) {
        // class literal
        Class<Sample> sampleClassLiteral = Sample.class;

        final Sample superObject = new Sample();
        // dynamic class
        // `? extends Sample` because the dynamic type could be a subclass
        Class<? extends Sample> superClassMethod = superObject.getClass();
        // classes are comparable both by == and equals, because `Class` is final and it does not override the default equals implementation
        assert sampleClassLiteral == superClassMethod;
        assert sampleClassLiteral.equals(superClassMethod);

        Sample subObject = new SubSample();
        // dynamic class can be different from the static type of the variable
        Class<? extends Sample> subSampleMethod = subObject.getClass();
        assert subSampleMethod != superClassMethod;

        SubSample staticCast = ((SubSample) subObject);

        List<Object> listOfAny = List.of(superObject, subObject, sampleClassLiteral, "some string", 12);
        // static type check & casting
        final List<Sample> listOfSample = listOfAny.stream()
                .filter(elem -> elem instanceof Sample) // Sample.class::isInstance
                .map(elem -> (Sample) elem)             // Sample.class::cast
                .collect(toList());

        final List<Sample> samples = listOfTargetClass(listOfAny, Sample.class);
        final List<? extends Sample> sameAsSamples = listOfTargetClass(listOfAny, superClassMethod);
        // [superObject, subObject] : does NOT contain `sampleClassLiteral` because it's not of type `Sample`, it is of type `Class<Sample>`
        System.out.println(samples);
        System.out.println(sameAsSamples);
        assert samples.equals(sameAsSamples);

        final List<SubSample> subSamples = listOfTargetClass(listOfAny, SubSample.class);
        System.out.println(subSamples);
    }

    static <T> List<T> listOfTargetClass(Collection<?> anyCollection, Class<T> targetClass) {
        // dynamic type check and casting
        return anyCollection.stream()
                .filter(targetClass::isInstance) // obj -> targetClass.isInstance(obj)
                .map(targetClass::cast) // obj -> targetClass.cast(obj)
                .collect(toList());
    }

    static class Sample { }

    static class SubSample extends Sample { }

}

I previously thought that sampleClass.class == SampleClass, an object of type Class.

You were very close. The correct understanding is that sampleClass.getClass() == SampleClass.class , an instance of the class Class .

SampleClass itself is a type, not a value. (In Java that's a firm distinction.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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