In Java, how do I ensure a dummy class is never used? - java

I am working on a project in which, to resolve a versioning issue, I am creating many classes which will never be tested and must not ever be used - they just need to be there to keep the compiler happy. I'd like to make sure they are never used. This morning I had the idea of throwing an exception in a static initialization block:
public class Dummy {
static {
throw new IllegalStateException("Do not use this class!");
}
}
But the compiler doesn't like it. Can you think of any way to do this?
EDIT: to be clear (my fault I wasn't clear before), these won't just be empty classes. There will be all sorts of code in here, and by "keep the compiler happy" I did indeed mean that elsewhere I will be instantiating them, calling methods etc etc. I want this code elsewhere to compile but fail at runtime. I have accepted Jon's answer but will also be using #Deprecated and documenting extensively as appropriate.

#Deprecated
A program element annotated #Deprecated is one that programmers are discouraged from using, typically because it is dangerous, or because a better alternative exists. Compilers warn when a deprecated program element is used or overridden in non-deprecated code.

Just add a dummy condition:
public class Dummy {
static {
if (true) {
throw new IllegalStateException("Do not use this class!");
}
}
}
I'm not really sure I like this, but it may do what you want it to. Are you sure there's no alternatively which would let you get away without having a completely useless class like this?

Give it a private default constructor, and make the class final.

Assuming you don't want IllegalStateExceptions potentially being thrown in your production code, use assertions and make sure they are enabled on your QA/Test environment. The code is slightly nicer too:
public class Dummy {
static {
//This class should never be initialised!
assert false : "This class should never be initialised";
}
...
}

You may get around the compiler with something like:
public class Dummy {
static {
if (true)
throw new IllegalStateException("Do not use this class!");
}
}
But that would be cheating ;-)

If they are never referenced, make the classes default scope, so no other types outside of the package can see them. If they can't see them they can't reference them (without using reflection that is).
class Dummy {
//no-op
}

Why don't you just not put that class into the jar that gets deployed. That way it'll be there at compile time but if someone tried to access it at runtime you'll get a ClassNotFoundException.

Use AssertionError instead of IllegalStateException

I don't think you can do that, though you can put a #deprecated tag before the class declaration. This way the compiler will give you a warning if you try to use it, but it will still compile.

You could use your own ClassLoader and check every class against a black list of classes.

What do you mean by "use"? If you need to have them in there, it sounds like the compiler needs to be able to create the classes. However, if you don't want any instances of the class to be created, then create an Assertion or throw an exception in the actual constructor.

Related

Initialize (load) a java class with a java.lang.Class<T> instance

I have to admit that this is more a cosmetic issue, but the fact that I haven't found a more straight-forward solution makes me think I am probably missing something.
The thing is, my class (let's say Foo) has a very important static block where it registers itself (Foo.class) with a builder method in a Map, like this:
// somewhere in the class
static {
Bar.registerBuilder(Foo.class, Foo::build);
}
This makes it possibe to get a Foo builder from the Bar class, a bit like this:
// somewhere in a method
Foo foo = Bar.getBuilder(Foo.class).apply("Hello World");
(if the builder takes a String argument). However, the upper code example will only work if the Foo class was already initialized. If not, this means the static block of Foo wasn't executed and the builder isn't registered in Bar by now, which is leading to getBuilder() returning null and apply() throwing a NullPointerException.
Thanks to the internet (mostly StackOverflow) I found out that you can imperatively with Class.forName(String). But what really confuses me is that this method takes a String (therefore throws the checked ClassNotFoundException) and I haven't found a way to load and initialize a class directly via a java.lang.Class instance. I would have expected something like
Class<Foo> clazz = Foo.class;
clazz.load(); // does not exist
Instead I have to do this:
Class<Foo> clazz = Foo.class;
try {
Class.forName(clazz.getName());
} catch (ClassNotFoundException) {
// handle an exception that is actually unreachable
}
I would like to know if I am completely missing something, or if not, if there is a cleaner way to load and initialize a class via the java.lang.Class representation.
Any help is appreciated, thank you!
EDIT 1: As #Boris the Spider pointed out in the comments, Foo.class should probably already load and initialize the class, but it doesn't (in my case, at least) and that's why I even encountered this problem.
EDIT 2: Using the "complicated" way to load the class via Class.forName() (as in the code example) actually resolves the problem as I thought. It's just that I'd like to use a cleaner way if possible.
Using:
Java 11 (openjdk 11.0.2)
IntelliJ IDEA Ultimate (2019.3)
Maven (3.6.3)
If you are already referencing the class it would be much better to move that static code into normal static factory method. As why would you use reflections or try to reference some class just to make some code run when you can just run that method?
public static BuilderFunction createBuilder() {
return Foo::build;
}
And just call it in static block of Bar:
registerBuilder(Foo.class, Foo.createBuilder());
If you need something more dynamic you can use service loaders, especially with java 9+ as they are much nicer now to use:
provides my.BuilderProvder with something.FooProvider;
And just load them all in Bar:
ServiceLoader<BuilderProvder> loader = ServiceLoader.load(BuilderProvder.class);
loader.stream()
.forEach(provider -> registerBuilder(provider));
now even different modules not developed by you can provide own builders and you don't need to do any manual class loading (and class initialization is only guaranteed to happen if class is actually used, like some method or field used - note that constants are inlined at compilation so they don't count).
You can also use some hacky reflection libraries like ClassGraph or Reflections to get all classes of given type/with given annotation and then load them and invoke some init method on them all just like in my first proposed solution with createBuilder. This is how many components inside spring are registered, similar thing can be done with java annotation preprocessing to find this classes at compile time and just save the names. But if possible I would suggest sticking to existing build in solutions like service loaders.

Calling static methods using an instance of that class [duplicate]

I'm sure you all know the behaviour I mean - code such as:
Thread thread = new Thread();
int activeCount = thread.activeCount();
provokes a compiler warning. Why isn't it an error?
EDIT:
To be clear: question has nothing to do with Threads. I realise Thread examples are often given when discussing this because of the potential to really mess things up with them. But really the problem is that such usage is always nonsense and you can't (competently) write such a call and mean it. Any example of this type of method call would be barmy. Here's another:
String hello = "hello";
String number123AsString = hello.valueOf(123);
Which makes it look as if each String instance comes with a "String valueOf(int i)" method.
Basically I believe the Java designers made a mistake when they designed the language, and it's too late to fix it due to the compatibility issues involved. Yes, it can lead to very misleading code. Yes, you should avoid it. Yes, you should make sure your IDE is configured to treat it as an error, IMO. Should you ever design a language yourself, bear it in mind as an example of the kind of thing to avoid :)
Just to respond to DJClayworth's point, here's what's allowed in C#:
public class Foo
{
public static void Bar()
{
}
}
public class Abc
{
public void Test()
{
// Static methods in the same class and base classes
// (and outer classes) are available, with no
// qualification
Def();
// Static methods in other classes are available via
// the class name
Foo.Bar();
Abc abc = new Abc();
// This would *not* be legal. It being legal has no benefit,
// and just allows misleading code
// abc.Def();
}
public static void Def()
{
}
}
Why do I think it's misleading? Because if I look at code someVariable.SomeMethod() I expect it to use the value of someVariable. If SomeMethod() is a static method, that expectation is invalid; the code is tricking me. How can that possibly be a good thing?
Bizarrely enough, Java won't let you use a potentially uninitialized variable to call a static method, despite the fact that the only information it's going to use is the declared type of the variable. It's an inconsistent and unhelpful mess. Why allow it?
EDIT: This edit is a response to Clayton's answer, which claims it allows inheritance for static methods. It doesn't. Static methods just aren't polymorphic. Here's a short but complete program to demonstrate that:
class Base
{
static void foo()
{
System.out.println("Base.foo()");
}
}
class Derived extends Base
{
static void foo()
{
System.out.println("Derived.foo()");
}
}
public class Test
{
public static void main(String[] args)
{
Base b = new Derived();
b.foo(); // Prints "Base.foo()"
b = null;
b.foo(); // Still prints "Base.foo()"
}
}
As you can see, the execution-time value of b is completely ignored.
Why should it be an error? The instance has access to all the static methods. The static methods can't change the state of the instance (trying to is a compile error).
The problem with the well-known example that you give is very specific to threads, not static method calls. It looks as though you're getting the activeCount() for the thread referred to by thread, but you're really getting the count for the calling thread. This is a logical error that you as a programmer are making. Issuing a warning is the appropriate thing for the compiler to do in this case. It's up to you to heed the warning and fix your code.
EDIT: I realize that the syntax of the language is what's allowing you to write misleading code, but remember that the compiler and its warnings are part of the language too. The language allows you to do something that the compiler considers dubious, but it gives you the warning to make sure you're aware that it could cause problems.
They cannot make it an error anymore, because of all the code that is already out there.
I am with you on that it should be an error.
Maybe there should be an option/profile for the compiler to upgrade some warnings to errors.
Update: When they introduced the assert keyword in 1.4, which has similar potential compatibility issues with old code, they made it available only if you explicitly set the source mode to "1.4". I suppose one could make a it an error in a new source mode "java 7". But I doubt they would do it, considering that all the hassle it would cause. As others have pointed out, it is not strictly necessary to prevent you from writing confusing code. And language changes to Java should be limited to the strictly necessary at this point.
Short answer - the language allows it, so its not an error.
The really important thing, from the compiler's perspective, is that it be able to resolve symbols. In the case of a static method, it needs to know what class to look in for it -- since it's not associated with any particular object. Java's designers obviously decided that since they could determine the class of an object, they could also resolve the class of any static method for that object from any instance of the object. They choose to allow this -- swayed, perhaps, by #TofuBeer's observation -- to give the programmer some convenience. Other language designers have made different choices. I probably would have fallen into the latter camp, but it's not that big of a deal to me. I probably would allow the usage that #TofuBeer mentions, but having allowed it my position on not allowing access from an instance variable is less tenable.
Likely for the same logical that makes this not an error:
public class X
{
public static void foo()
{
}
public void bar()
{
foo(); // no need to do X.foo();
}
}
It isn't an error because it's part of the spec, but you're obviously asking about the rationale, which we can all guess at.
My guess is that the source of this is actually to allow a method in a class to invoke a static method in the same class without the hassle. Since calling x() is legal (even without the self class name), calling this.x() should be legal as well, and therefore calling via any object was made legal as well.
This also helps encourage users to turn private functions into static if they don't change the state.
Besides, compilers generally try to avoid declaring errors when there is no way that this could lead to a direct error. Since a static method does not change the state or care about the invoking object, it does not cause an actual error (just confusion) to allow this. A warning suffices.
The purpose of the instance variable reference is only to supply the type which encloses the static. If you look at the byte code invoking a static via instance.staticMethod or EnclosingClass.staticMethod produces the same invoke static method bytecode. No reference to the instance appears.
The answer as too why it's in there, well it just is. As long as you use the class. and not via an instance you will help avoid confusion in the future.
Probably you can change it in your IDE (in Eclipse Preferences -> Java -> Compiler -> Errors/Warnings)
There's not option for it. In java (like many other lang.) you can have access to all static members of a class through its class name or instance object of that class. That would be up to you and your case and software solution which one you should use that gives you more readability.
It's pretty old topic but still up-to-date and surprisingly bringing higher impact nowadays. As Jon mentioned, it might be just a mistake Java's designers made at the very beginning. But I wouldn't imagine before it can have impact on security.
Many coders know Apache Velocity, flexible and powerful template engine. It's so powerful that it allows to feed template with a set of named objects - stricly considered as objects from programming language (Java originally). Those objects can be accessed from within template like in programming language so for example Java's String instance can be used with all its public fields, properties and methods
$input.isEmpty()
where input is a String, runs directly through JVM and returns true or false to Velocity parser's output). So far so good.
But in Java all objects inherit from Object so our end-users can also put this to the template
$input.getClass()
to get an instance of String Class.
And with this reference they can also call a static method forName(String) on this
$input.getClass().forName("java.io.FileDescriptor")
use any class name and use it to whatever web server's account can do (deface, steal DB content, inspect config files, ...)
This exploit is somehow (in specific context) described here: https://github.com/veracode-research/solr-injection#7-cve-2019-17558-rce-via-velocity-template-by-_s00py
It wouldn't be possible if calling static methods from reference to the instance of class was prohibited.
I'm not saying that a particular programming framework is better than the other one or so but I just want to put a comparison. There's a port of Apache Velocity for .NET. In C# it's not possible to call static methods just from instance's reference what makes exploit like this useless:
$input.GetType().GetType("System.IO.FileStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
I just consider this:
instanceVar.staticMethod();
to be shorthand for this:
instanceVar.getClass().staticMethod();
If you always had to do this:
SomeClass.staticMethod();
then you wouldn't be able to leverage inheritance for static methods.
That is, by calling the static method via the instance you don't need to know what concrete class the instance is at compile time, only that it implements staticMethod() somewhere along the inheritance chain.
EDIT: This answer is wrong. See comments for details.

Omitting throws declarations in derived classes

Consider the following interface:
public interface Generator {
String generate() throws IOException;
}
and the following implementation:
public class EmptyStringGenerator implements Generator {
#Override
public String generate() {
return "";
}
}
Note that I omitted the throws IOException part of the signature specified in the Generator interface. Yet there is no compiler error, no compiler warning, not even the #Override annotation complains.
I am aware that this is working as intended. I would, however, like to know the intent behind this. If my method does not actually throw an IOException, it would be fine to just not throw it, I do not have to remove it from the signature. But if I do remove it from my method signature in EmptyStringGenerator, I am forcing all current and future subclasses of this class to forego the possibility of throwing an exception that is actually specified in the interface.
This, to me, sounds like a feature that does not really bring you any benefit (apart from saving a couple of keystrokes, which is not really a benefit at all), but has the potential to be a terrible mistake, when actually used.
So my question, effectively, is this: What is the point of omitting throws exceptions in derived classes? What is the problem that this possibility solves? Why is this allowed?
UPDATE
For people asking "but where is the harm in that?", here is my example from one of my comments. It is not far-fetched, by the way, because that is exactly what I am dealing with right now:
Programmer A specifies interface I. Programmer B writes implementation class X, but forgets to add the throws. He also never notices, because there is not even a warning being thrown here. Programmer C writes implementation class Y, inheriting from class X, he even specifically also wants to put the throws there, because he is gonna throw. But even though the interface stipulates it, he is now not allowed to do so anymore, because of B's oversight. He is effectively not allowed to use that exception here anymore. That's a pretty big harm. Especially if class X is not under your control.
If you omit the throws exception in derived classes you can call the method of the derived class without having to catch the exception.
You make sure that subclasses of EmptyStringGenerator also don't throw an exception. Otherwise it would not be sure for the compiler if the method call can cause a checked exception which the code must handle. In that case the throws wouldn't make sense at all.
Based on your class decleration, campare these two conditions:
EmptyStringGenerator generator = new EmptyStringGenerator();
generator.generate();
if you create an instance of EmptyStringGenerator like above, Since you omit the throws in EmptyStringGenerator, the above code indicates you are using the class itself, which of course has nothing to do with the interface, so the code works just fine.
but if you intend to use the interface instead of the class, like this:
Generator generator = new EmptyStringGenerator();
generator.generate();
than the compiler would actually remind you that there is an unhandled exception, you must handle it with a try-catch or throw it, otherwise the code will not compile.
if you use any subclass of EmptyStringGenerator in the latter manner, the same compile error will occur. So omitting the throw does not actually rlease you from handling the exception. It's only natural not to throw exception in a class and its subclasses when there is none to throw, but When you are calling the method through the interface, the exception still has to be handle.
In Java its OK and normal that you can make your classes less restrictive when implementing or extending that is a design decision of the Java developer. I can not say why Sun decided it this way and of course I can understand your problem with it, but the current way also has some benefits.
I see an Interface as a possibility to have multiple implementations for one job. For example the List classes which have different implementations for different needs. But they can all be used via the List interface. Lets say the remove method throws a CheckedException if the element is not part of the list. Now if am not able to be less restrictive in my implementations all List classes must throw this CheckedException, even they do not need or use it.
So if I use the remove method internally in my Class I am forced to handle the CheckedException. If I use my List class directly without the Interface I am forced to catch the exception. But for both cases I am pretty sure I do not need it and it will never happen. So with the current approach I can save a lot of "try catch ignore" blocks.
An other benefit of the current solution is that a class can easily match similar Interfaces.
So for example in one lib someone added a:
public interface Generator {
String generate() throws IOException;
}
And in an other lib:
public interface GeneratorInterface {
String generate();
}
If I write a Class with a generate method without any CheckedException I can easily use this to satisfy both Interfaces and maybe work with both libs:
public class EmptyStringGenerator implements Generator,GeneratorInterface {
#Override
public String generate() {
return "";
}
}
Also as far as I know Java is the only language with such handling of Checked and Unchecked exceptions and so the design decisions which pull through Java are strange compared with other languages not having Checked exceptions.

Creating a new Exception type - write all constructors or only those needed?

When I write a new exception type, am I supposed to write only the constructors needed, or implement all constructors exisiting in Throwable (and calling them by super())?
When thinking about it, I would say implement only what is needed (YAGNI - You Ain't Gonna Need It). If I need another constructor later, I just add it.
Example:
public void MyException extends RuntimeException {
// I only need this constructor
public MyException(Throwable cause) {
super(cause);
}
}
Only implement what you'll need and add as you need them. I usually add the one with the String message and the one you have (for wrapping another Exception).
It depends what you are writing for.
For a small program, do not write dead code.
If the class is going into a library or will be used by other team/team-members where there is some kind of code ownership going on, then write the complete class. Be careful with this: "speculative generalisation" is a serious problem in software development.
Yes, you should implement just the ones you are going to need.
Systems around that I work/worked wich, usually implements at least a constructor that receives the exception cause (exactly like your example). Also an exception defining only a default constructor won't do make much sense unless it's something very very very specific.
Best regards.

Does a Java class get loaded if I access MyClass.class.getName()?

I want to explicitly initialize some classes during the initialization of my application using Class.forName, but in order make that code survive refactorings, I want to use this:
Class.forName(MyClass.class.getName());
I wonder: Wouldn't the class be loaded as soon as the getName method is executed thus making Class.forName unnecessary?
Actually, even the getName() call is unnecessary, since in order for the MyClass.class object to exist, the class has to be loaded and initialized.
Of course, this method means that you have a compile-time dependency on MyClass, which you do not have when using Class.forName() with a String literal.
You can easily check this out. Just add something like this:
static { System.out.println("Class loaded"); }
in the class and try it. Static blocks are executed when the class is loading.
I just found out: -verbose:class shows all class loading events.
As Michael Borgwardt says, the simplest statement to achieve your aim is MyClass.class.
You might want to assign the value returned to something just in case the compiler ever decided that the statement had no side effects and could be optimized away, but I don't believe that any do.

Categories

Resources