An interesting early exercise. My comments are mostly about style, obviously, since you have the code running correctly. Congratulations, by the way.
I have set up VampireNumber to be a class that only holds numbers that have tested to fit that definition. The constructor goes through the
test, and throws an exception if the number fails.
Someone interested in compute-time efficiency could well argue that the test should be done outside a constructor; that constructing an object, even partially, is an expensive computing operation that we do not need to do most of the time. If I were interested in compute-time efficiency, I would make a static method that checked whether a number was a vampire, and only construct the object if it were.
I think a static method fits well in that version -- it is directly and only concerned with vampire numbers, but is not needed for an instance of the class.
Any time I see a repeating
pattern in code such as your "result = calc(...); if (result == number) {...}", I look for some way to reduce it to its essentials. It reduces code, sometimes dramatically, but more importantly, to me, it allows me to examine patterns in the essentials much more easily. Look at what I've done with that -- I submit that it is far easier to tell, in my version, what combinations of four numbers are submitted to testing than in your version. I think this is the biggest advantage -- not reducing lines just by itself, not any kind of runtime efficiency, but that anyone reading the code can tell more easily what it is doing, at either a detailed level or an overall level.
I put the number beginning your loop into the beginning of your loop. Perhaps you didn't know you could declare the loop variable within the "for" statement. Again, just style, but I think most readers of Java would find this a very little bit more understandable.
Anyway, here is my version. No doubt we can improve it further.