3

Consider the simplest possible example. We have

public class Foo {}

Therefore we can say

Foo.class // ==> class Foo

It therefore stands to reason that Foo should be a java.lang.Class, as we clearly have access to it and can manipulate it in the current context. Yet

Foo instanceof java.lang.Class

raises the error

cannot find symbol
  symbol:    variable Foo
Foo instanceof java.lang.Class
^-^

This isn't anything to do with instanceof itself, though; just

Foo

alone in the OpenJDK shell produces the same error.

How can we be accessing properties on Foo if Foo does not exist in the current context?

  • Please expand on what you mean, `Foo` is not a **variable** it is a `class`. How could a class be an instance of some type besides `Class`? – Elliott Frisch Oct 30 '19 at 23:29
  • @ElliottFrisch The `instanceof Object` line was just an example, such as to show that `Foo` doesn't seem to act in a consistent way between `Foo instanceof x` and `Foo.class`. – Curtis Parfitt-Ford Oct 30 '19 at 23:32
  • 1
    @Blorgbeard I don't think this is a duplicate - looking there, it's not clear to me why `Foo.class` would get the property on the `java.lang.Class` instance whereas `Foo instanceof x` wouldn't. – Curtis Parfitt-Ford Oct 30 '19 at 23:33
  • 2
    I was thinking in particular of [this answer](https://stackoverflow.com/a/11990369/369). `Foo` is a class. It's not a `java.lang.Class`, it's not an object. It's just a symbol. You can use symbols that refer to classes in different ways than symbols that refer to variables. E.g. `class Bar extends Foo` is valid, but `class Bar extends myObject` is nonsensical. One of the things you can do with a class symbol is get an object (java.lang.Class) that represents the class, which you do with `Foo.class`. So `Foo instanceof x` doesn't make sense, because `Foo` doesn't refer to a variable. – Blorgbeard Oct 30 '19 at 23:41
  • 1
    Also note that `Foo.class` is not really "accessing a property" in the same way as "myObject.getProperty()" is. It's just separate syntax that looks similar. – Blorgbeard Oct 30 '19 at 23:44
  • `Foo.class` is of type `Class`. `Foo` is a class, not an instance of type `Class`. Only its attribute `class` is. And `Foo instanceof x` is not valid Java, as stated above. – Lew Bloch Oct 31 '19 at 19:32

2 Answers2

7

A class name may be used in your source code as a part of many different expressions. It doesn't mean that the class name itself is an object; it just means that the name itself can be used as part of a bigger expression. These are not "properties" or attributes; they are other syntactical constructions used to form expressions with many different parts.

The JLS defines how a "TypeName", e.g. Foo can be used to form expressions in Chapter 15. Specifically:

It may also be a "Reference Type" eligible for other expressions, such as:

There are specific uses of a type name e.g. Foo that are described above. This does not imply that the type name can be used generally as its own object. Type names are allowed only as part of larger expressions that can be otherwise unrelated.

rgettman
  • 176,041
  • 30
  • 275
  • 357
3

Foo is a type. Foo.class is an object that represents a type.

The instanceof operator takes an object as its first argument and a type as its second argument. Foo doesn't work as a first argument because it isn't an object- it's a type.

As for why you can do Foo.class... well, that's just the way Java syntax works. The structure of the class itself is known during runtime and is represented by a Class object which is shared by all instances of that class. The .class syntax is one way of accessing that object.

mario_sunny
  • 1,412
  • 11
  • 29
  • Thanks. That'd make sense, were it giving some kind of error about an invalid type being presented to `instanceof` - but it's not, it's saying there's literally nothing called `Foo` in scope. Even just typing `Foo` and hitting Enter in an OpenJDK shell produces that response. – Curtis Parfitt-Ford Oct 30 '19 at 23:40
  • 1
    Note that your error says that it can't find a symbol that matches "variable Foo". This makes sense, because Foo is not a variable. – Blorgbeard Oct 30 '19 at 23:43
  • So why do you not get an error about a missing variable `Foo` when doing `.class`? – Curtis Parfitt-Ford Oct 30 '19 at 23:44
  • 1
    Because a class name followed by `.class` is valid syntax. It's not looking for a variable, it requires a class. – Blorgbeard Oct 30 '19 at 23:46
  • So effectively `.class` on a type is just "that's the way it is", then - it's reading it and looking specifically for that and nothing else? That seems... very odd. – Curtis Parfitt-Ford Oct 30 '19 at 23:47
  • @CurtisParfitt-Ford What is odd about it, the syntax of it or what is returned by it? – mario_sunny Oct 30 '19 at 23:48
  • The syntax. To me, it seems very strange to be able to do something that looks like accessing a property on something that for all other intents and purposes the language decides does not exist. – Curtis Parfitt-Ford Oct 30 '19 at 23:50
  • How else would you expect the syntax to look if you wanted to access the `Class` object of a type within a static context? – mario_sunny Oct 30 '19 at 23:52
  • "That seems ... very odd" is an expression of bias. "Seems" is a subjective term, meaning "I assess that". The problem here isn't whether Java's long-standing, well-documented syntax is "odd", but whether a person subjectively feels that it is. Such feelings have little to do with engineering assessment. – Lew Bloch Oct 31 '19 at 19:34