Anonymous class binary names - java

I have the following problem:
1) There is some abstract class A with several anonymous subclasses stored in the static fields of A. There is circular dependency between two of the anonymous subclasses. The code of that abstract class is similar to following:
class A implements Serializable
{
public static final A _1 = new A() {
public A foo()
{
return _2;
}
};
public static final A _2 = new A() {
public A foo()
{
return _1;
}
};
public static final A _3 = new A() {
public void bar()
{
// do something
}
};
}
2) Instances of class A is referenced by other objects which are used in serialization. There are some objects which are pre-serialized by developers and then included into release as binary data.
After some refactoring of A class binary names of anonymous subclasses was changed in the release builds. I think this may be due to difference of java compiler versions. From .class files made on my machine I can see that anonymous subclasses of A stored in _1, _2 and _3 fields have names A$1, A$2 and A$3, respectively, but from .class files taken from release build I can see that anonymous subclasses of A stored in _1, _2 and _3 fields have names A$2, A$3 and A$1, respectively. Due to this pre-serialized data became unusable and I need to fix this somehow.
Are there any specifications for java compilers or JVM which will say what binary names I should expect for my anonymous classes? The JLS says that name of anonymous class should be name of enclosing class, "$"-sign and non-empty sequence of digits without setting any constraints on these sequences.
I believe that I shouldn't rely on internal names of anonymous classes, I also know "proper" ways to fix that problem like generating pre-serialized data on the build server. Too bad we don't have much time for this now, so I want to know from where this naming difference comes, so I could fix this issue now.

May I dare to challenge some elements ? Hopefully it can be useful to you :
if you want your classes to have a well-known name ... well, anonymous is the contrary of a named class ! ;-)
preserializing and delivering objects as binary data is a dangerous choice, and you got bitten by it (during a refactoring, but I believe that could happen in many other conditions). Serialized data is usually considered as a short term solution in Java, good for a few seconds. Many other options are available for longer term storage.
Now, if asked to solve your short-term problem, the only approach I see is to restore your classes to a state compatible with the previous version. If the different ordering you mention is the only difference, I believe that defining the anonymous classes in the same order as before is worth trying ! Also take care that references should be backwards (to a class earlier in the file), not forward (to a class later in the file).

The only reason I can guess why it fails is that the new Java version reorders the class names because you reference _2 in _1. That said, I don't think you can rely on the names since Java makes no guarantees in which order it will process fields of a class (and therefore, the sequence in which it will create inner classes).
But I think your problem is somewhere else. What error do you get?

Did your compiler not give any warnings?
I believe you can read the data without relying on the anonymous class names in the current code by overriding ObjectInputStream.readClassDescriptor. Replace with a descriptor of a "compatible" class. No guarantees that will work, but may be worth a try if your data is important.

Related

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.

Java Obscured Obfuscation

Similar Questions: Here and Here
I guess the situation is pretty uncommon to begin with, and so I admit it is probably too localized for SO.
The Problem
public class bqf implements azj
{
...
public static float b = 0.0F;
...
public void b(...)
{
...
/* b, in both references below,
* is meant to be a class (in the
* default package)
*
* It is being obscured by field
* b on the right side of the
* expression.
*/
b var13 = b.a(var9, var2, new br());
...
}
}
The error is: cannot invoke a(aji, String, br) on primitive type float.
Compromisable limitations:
Field b cannot be renamed.
Class b cannot be renamed or refactored.
Why
I am modifying an obfuscated program. For irrelevant[?], unknown (to me), and uncompromisable reasons the modification must be done via patching the original jar with .class files. Hence, renaming the public field b or class b would require modifying much of the program. Because all of the classes are in the default package, refactoring class b would require me to modify every class which references b (much of the program). Nevertheless there is a substantial amount of modification I do intend on doing, and it is a pain to do it at the bytecode level; just not enough to warrant renaming/refactoring.
Possible Solutions
The most obvious one is to rename/refactor. There are thousands of classes, and every single one is in the default package. It seems like every java program I want to modify has that sort of obfuscation. : (
Anyways sometimes I do take the time to just go about manually renaming/refactoring the program. But when when there's too many errors (I once did 18,000), this is not a viable option.
The second obvious option is to do it in bytecode (via ASM). Sometimes this is ok, when the modifications are small or simple enough. Unfortunately doing bytecode modifications on only the files which I can't compile through java (which is most of them, but this is what I usually try to do) is painfully slow by comparison.
Sometimes I can extend class b, and use that in my modified class. Obviously this won't always work, for example when b is an enum. Unfortunately this means a lot of extra classes.
It may be possible to create a class with static wrapper methods to avoid obscurity. I just thought of this.
A tool which remaps all of the names (not deobfuscate, just unique names), then unmaps them after you make modifications. That would be sweet. I should make one if it doesn't exist.
The problem would also be solved with a way to force the java compiler to require the keyword "this".
b.a(var9, var2, new br());
can easily be rewritten using reflection:
Class.forName("b").getMethod("a", argTypes...).invoke(null, var9, var2, new br());
The problem would also be solved with a way to force the java compiler to require the keyword "this".
I don't think how this would help you for a static member. Compiler would have to require us to qualify everything—basically, disallow simple names altogether except for locals.
Write a helper method elsewhere that invokes b.a(). You can then call that.
Note: In Java the convention is that the class would be named B and not b(which goes for bqf and aqz too) and if that had been followed the problem would not have shown.
The real, long time cure, is not to put classes in the default package.

Java: Code structure & class naming of primitive-type variants - best practices

Recently, I have been writing many classes which have, apart from generic variant, some primitive variants, for example Foo<T>, IntFoo, DoubleFoo etc. First, I used to put every variant in separate files but I soon found out that the package content has become unreadable due to large number of classes with similar names. On the other hand, putting those in a separate package often results in a loss of cohesion and extra dependencies between packages.
In the meanwhile, I have come to the idea to have the following structure:
public class Foo {
public static class TypeFoo<T> { ... }
public static class IntFoo { ... }
public static class DoubleFoo { ... }
...
}
or
public class Foo {
public static class Type<T> { ... }
public static class Int { ... }
public static class Double { ... }
}
I am interested in two things:
Does any of these two approaches result in greater overhead when using only one inner class (e.g. int-variant of the class), compared to one-class-per-file approach? Does this overhead, if any, applies when there are inner interfaces instead?
Which of these two approaches is better, if any, or if none is good, what are the alternatives?
inner classes will be more of a pain in the long run, in my opinion. if you look at the way Microsoft named their animation classes, they had the same dilemma that you did. They chose to have tons of different classes, but as a consumer of these I have found that I prefer it to be this way.
to answer your first question, there should be no overhead. When java compiles inner classes it separates them into separate *.class files anyway, so in the end the result is the same. During compilation the parser will have to sift through a lot of Foo.* references but the extra time would be negligible.
Might be completely irrelevant to what you're doing, but you could consider replacing all these classes with a Builder (or otherwise known as Fluent Interface) pattern. If these classes implement a generic interface, you shouldn't need to expose them anywhere and can still keep them inside one builder class.
A good example of this would be MapMaker which probably has zillion different inner classes but the only thing you care about is the Map or ConcurrentMap instance you get out of it.

Java abstract static Workaround

I understand that neither a abstract class nor an interface can contain a method that is both abstract and static because of ambiguity problems, but is there a workaround?
I want to have either an abstract class or an interface that mandates the inclusion of a static method in all of the classes that extend/implement this class/interface. Is there a way to do this in Java? If not, this may be my final straw with Java...
EDIT 1: The context of this problem is that I have a bunch of classes, call them Stick, Ball, and Toy for now, that have a bunch of entries in a database. I want to create a superclass/interface called Fetchable that requires a static method getFetchables() in each of the classes below it. The reason the methods in Stick, Ball, and Toy have to be static is because they will be talking to a database to retrieve all of the entries in the database for each class.
EDIT 2: To those who say you cannot do this in any language, that is not true. You can certainly do this in Ruby where class methods are inherited. This is not a case of someone not getting OO, this is a case of missing functionality in the Java language. You can try to argue that you should never need to inherit static (class) methods, but that is utterly wrong and I will ignore any answers that make such points.
You have a couple of options:
Use reflection to see if the method exists and then call it.
Create an annotation for the static method named something like #GetAllWidgetsMethod.
As others have said, try to not use a static method.
There are lots of answers about 'this does'nt make sense..' but indeed I met a similar problem just yesterday.
I wanted to use inheritance with my unit tests. I have an API and several its implementations. So I need only 1 set of unit tests for all implementations but with different setUp methods which are static.
Workaround: all tests are abstract classes, with some static fields with protected access modifier. In all implementations I added static methods which set these static fields. It works rather nice, and I avoided copy and paste.
I too am dealing with this problem. For those that insist that it "doesn't make sense", I would invite you to think outside of that semantic box for a moment. The program I am working with is inherently about reflection.
Reflection, as you know, can take three orders of magnitude longer than straight-up binary function calling. That is an inevitable problem, and the software needs to port to as many machines as possible, some of which will be 32 bit and slower than my development machine to begin with. Thus, the applicability of a class to the requested operation needs to be checked via a static method, and all of the reflective methods are run at once during module booting.
Everything works, first and foremost. I've built the entire thing. The only catch is that a module can be compiled in a .class without compile time checking to see if the identifying static function exists at all, resulting in an innately useless class. Without the identifier, and its included information, for security's sake the module is not loaded.
I clearly understand the issue with the complete definition of "abstract" and "static", and understand that they don't make sense together. However, the ability to have a class method that is compiler-enforced for inclusion is lacking in Java, and as much as I like the language, I miss it. Thus, this is a human constraint on every programmer that ever works on the software, which I'm sure we can all agree is a pain.
There's a lot of 'this makes no sense' or 'this can't be because' and 'why do you want it?' (or worse: 'you don't have to want it!') in all those answers. However, these answers also indirectly give reasons why it should be possible.
It must be differentiated between the concept and the implementation.
Sure, overriding a static method makes no sense. And it also isn't what the question was about.
It was asked for a way to force implementation of a certain static method (or constant or whatever) in every derived class of an abstract class. Why this is required it the matter of the one who wants to write an appllication with Jave, and no business of anyone else.
This has nothing to do with how the compiler compiles the method and how it is done at runtime.
Why shoudl it be possible? because there are things that are class specific (and not instance specific) and therefore should be static, while they NEED to be impleented in every single subclass (or class that implements an interface).
Let's say there is an abstract class 'Being'. Now there are subclasses like 'animals' and 'plants'.
Now there are only mammals and fishes allowed for animals. This information is specific to the animals class, not to any instance nor doe sit belong to any superclass or subclass. However, this information must be provided by teh class, not an instance, because it is required to properly construct an animal instance. So it MUST be there and it CANNOT be in the instance.
In fact, Java has such a thing- Every object has a class specific field 'class'. It is class-specific, not inherited, no override and it must be there. Well the compiler creates it implicitly, but obviously the compiler CAN do it. So why not allowing this for own fields too.
After all, it is just a matter of definition how the combination 'abstract static' is interpreted when the compiler checks the intheritance chain for abstract functions.
Nobody was ever demanding that there should be an inheritance of the superclass class functions (which could still make some sense, depending on what this function actually does - after all classes inherit static functions of their superclasses, even though you might get a warning that you should access it directly when you call it by the subclass))
But to summarize: the Java language offers no way to do it at compile time while there is no reason (othe rthan plain dogmatic) to not doing so.
The only way is to write a static final function to the abstract class that tries to find the static function/field of the subclass when it is loaded (or loads all existing subclasses and checks them). If properly made, it gives a runtime error on first use. Complex and dirty but better than nothing. At least it prevents bugs where you get the information from the wrong superclass.
It won't work for interfaces, though.
A type system allows you to express some constraints among types, but it's limited. That's why javadocs are littered with constraints in human language, asking people to follow rules that the compiler cannot check.
if you want to extend it beyond what language provides natively, you can write your own static analysis tool. that is not uncommon. for example: findbug. also IDEs do that too, they checking thing beyond what language dictates. you can write a plug in to enforce that a subclass must have a static method of such signature.
in your case, it's not worth it. have javadoc in the superclass urge implementors to include a static method, that's good enough.
I'll provide a convoluted way of expressing your constraint anyway, but DO NO DO IT. people get really carried away of make everything checkable at compile time, at the price of making code unreadable.
interface WidgetEnumerator
{
List getAllWidgets();
}
public class Abs<T extends WidgetEnumerator>
{
static List getAllWidgets(Class<? extends Abs> clazz){ ... }
}
public class Sub extends Abs<SubWidgetEnumerator>
{
}
public class SubWidgetEnumerator implements WidgetEnumerator
{
public List getAllWidgets() { ... }
}
How it works: for any subclass of Abs, it is forced to provide an implementation of WidgetEnumerator. subclass author cannot forget that. Now invocation Abs.getAllWidgets(Sub.class) contains sufficient information to resolve that implementation, i.e. SubWidgetEnumerator. It is done through reflection, but it is type safe, there are no string literals involved.
I think I can give you a better answer after seeing your edits--your best bet is probably a factory pattern. (Not lovely, but better than singleton).
abstract class Widget
public static Widget[] getAllWidgetsOfType(Class widgetType) {
if(widgetType instanceof ...)
}
class Ball extends Widget
class Stick extends Widget
class Toy extends Widget
This is not a very good way to do it, but it's typical. Hibernate is the tool you would normally use to solve this problem, this is exactly what it's designed for.
The big problem is that it requires editing the base class whenever you add a new class of a given type. This can't be gotten around without reflection. If you want to use reflection, then you can implement it this way (Psuedocode, I'm not going to look up the exact syntax for the reflection, but it's not much more complex than this):
public static Widget[] getAllWidgetsOfType(Class widgetType) {
Method staticMethod=widgetType.getStaticMethod("getAllInstances");
return staticMethod.invoke();
}
This would give the solution you were asking for (to be bothered by the need to modify the base class each time you add a child class is a good instinct).
You could also make it an instance method instead of a static. It's not necessary, but you could then prototype the method (abstract) in Widget.
Again, all this is unnecessary and sloppy compared to Hibernate...
Edit: If you passed in a live "Empty" instance of a ball, stick or toy instead of it's "Class" object, you could then just call an inherited method and not use reflection at all. This would also work but you have to expand the definition of a Widget to include an "Empty" instance used as a key.
Static methods are relevant to an entire class of object, not the individual instances. Allowing a static method to be overridden breaks this dictum.
The first thing I would consider is to access your database from a non-static context. This is actually the norm for Java apps.
If you absolutely must use a static method, then have it parameterised with instance specific arguments (of a generic type) to allow the different subclasses to interact with it. Then call that single static method from you polymorphic methods.
No. You can't do that. If you're willing to compromise and make the method non-static or provide an implementation of the static method in your abstract class, you'll be able to code this in Java.
Is there a way to do this in Java?
I don't think there is a way to do this in any language. There's no point to it, since static methods belong to a class and can't be called polymorphically. And enabling polymorphic calls is the only reason for interfaces and abstract classes to exist.
Create a context interface containing your method with a name that matches your problem domain. (Name it "World" if you absolutely have to, but most of the time there's a better name)
Pass around implementation instances of the context object.
Ok, maybe my question was poorly asked, it seems like most of you didn't get what I was trying to do. Nonetheless, I have a solution that is somewhat satisfactory.
In the abstract super class, I am going to have a static method getAllWidgets(Class type). In it I'll check the class you passed it and do the correct fetching based on that. Generally I like to avoid passing around classes and using switches on stuff like this, but I'll make an exception here.
static methods can't be abstract because they aren't virtual. Therefore anywhere that calls them has to have the concrete type with the implementation. If you want to enforce that all implementations of an interface have a certain static method, then that suggests a unit test is required.
abstract class A
{
public static void foo()
{
java.lang.System.out.println("A::foo");
}
public void bar()
{
java.lang.System.out.println("A::bar");
}
}
class B extends A
{
public static void foo()
{
java.lang.System.out.println("B::foo");
}
public void bar()
{
java.lang.System.out.println("B::bar");
}
}
public class Main
{
public static void main(String[] args)
{
B b = new B();
b.foo();
b.bar();
A a = b;
a.foo();
a.bar();
}
}
For what it is worth I know exactly what you are trying to do.
I found this article while searching for the reasons I can't do it either.
In my case I have HUNDREDS of classes that inherit from a central base base and I want simply to get a reference like this:
ValueImSearchingFor visf = StaticClass.someArbitraryValue()
I do NOT want to write/maintain someArbitraryValue() for each and every one of hundreds of the inherited classes -- I just want to write logic once and have it calc a Unique Class-Sepcific value for each and every future written class WITHOUT touching the base class.
Yes I completely get OO - I've been writing Java for about as long as it's been available.
These specific classes are more like "Definitions" as opposed to actual Objects and I don't want to instantiate one every time I just need to see what someArbitraryValue() actually is.
Think of it as a PUBLIC STATIC FINAL that allows you to run a Method ONCE to set it initially. (Kinda like you can do when you define an Enum actually...)
I'd make a WidgetCollection class with an abstract Widget inner class.
You can extend the WidgetCollection.Widget class for each of your types of Widget.
No static methods necessary.
Example (not compiled or tested):
class WidgetCollection<W extends Widget> {
Set<W> widgets = new HashSet<W>();
Set<W> getAll() {
return widgets;
}
abstract class Widget {
Widget() {
widgets.add(this);
}
abstract String getName();
}
public static void main(String[] args) {
WidgetCollection<AWidget> aWidgets = new WidgetCollection<AWidget>();
a.new AWidget();
Set<AWidget> widgets = aWidgets.getAll();
}
}
class AWidget extends Widget {
String getName() {
return "AWidget";
}
}
It doesn't make sense to do what you're asking:
Why can't static methods be abstract in Java

Java: refactoring static constants

We are in the process of refactoring some code. There is a feature that we have developed in one project that we would like to now use in other projects. We are extracting the foundation of this feature and making it a full-fledged project which can then be imported by its current project and others. This effort has been relatively straight-forward but we have one headache.
When the framework in question was originally developed, we chose to keep a variety of constant values defined as static fields in a single class. Over time this list of static members grew. The class is used in very many places in our code. In our current refactoring, we will be elevating some of the members of this class to our new framework, but leaving others in place. Our headache is in extracting the foundation members of this class to be used in our new project, and more specifically, how we should address those extracted members in our existing code.
We know that we can have our existing Constants class subclass this new project's Constants class and it would inherit all of the parent's static members. This would allow us to effect the change without touching the code that uses these members to change the class name on the static reference. However, the tight coupling inherent in this choice doesn't feel right.
before:
public class ConstantsA {
public static final String CONSTANT1 = "constant.1";
public static final String CONSTANT2 = "constant.2";
public static final String CONSTANT3 = "constant.3";
}
after:
public class ConstantsA extends ConstantsB {
public static final String CONSTANT1 = "constant.1";
}
public class ConstantsB {
public static final String CONSTANT2 = "constant.2";
public static final String CONSTANT3 = "constant.3";
}
In our existing code branch, all of the above would be accessible in this manner:
ConstantsA.CONSTANT2
I would like to solicit arguments about whether this is 'acceptable' and/or what the best practices are.
A class with only static fields is a code smell. It's not a class.
Some people use interfaces, so they can implement it to use the constants more easily. But an interface should be used only to model a behaviour of a class. (http://pmd.sourceforge.net/rules/design.html#AvoidConstantsInterface) Using static imports from Java 5 removes the need for simple constant usage at all.
Are your constants really Strings, or just used as Strings. If they are different options for some type (so called enumerations), you should used typesafe enumerations, using enum in Java 5 or the Enum provided by Commons Lang. Of course, converting your code to use enums might be a little work.
You should at least split the constants to groups of related constants in files with proper business name. Moving the final members is easy in IDE and will update all usages.
If you can afford it, convert them to enums then. (Think about using about a script to do that, often it's possible.) Class hierarchies are only usefull, if there is a relation between the constants/enums. You can keep the Strings if you have to but still think about them as entities, then extends might make sense for some (describing is-a relation). First enums can be simple classes made by yourself if serializing is not a problem. Enums are always favourable due to their type safe nature and the extra name showing intend or business/domain specific things.
If the constants are really String constants use a Properies or ResourceBundle, which can be configured by plain text files. Again you can script the refactoring using the constant names as resource bundle keys and generate both files automatically.
I don't like it, but it's probably the best you can do right now.
The right answer would be to break up the constants into coherent groups, fixing the code breaks as you go along. In C#, I'd use enums.
Peter Kofler has already discussed how you might wish to better organize constants. I'll share how to automate the transition:
The eclipse "Inline" refactoring can automatically replace constants by their defintion, saving you from having to hunt down and change each usage manually. So you'd simply change the code to:
public class ConstantsA {
public static final String CONSTANT1 = "constant.1";
public static final String CONSTANT2 = ConstantsB.CONSTANTFOO;
public static final String CONSTANT3 = ConstantsB.CONSTANTBAR;
}
public class ConstantsB {
public static final String CONSTANTFOO = "constant.2";
public static final String CONSTANTBAR = "constant.3";
}
... and then have eclipse inline COONSTANT2 and CONSTANT3 (while all affected projects are checked out, if you can't do that, look into refactoring scripts), and you're done.
I've seen this done by putting the static final String on an interface, so that you can 'implement' it and not have to worry about what to do when you need a different base class. It's just as accessible that way.
In general though, enums are pretty good at what you are trying to do, and may get rid of the "I'm not sure" feeling you are experiencing, as that's the intention of enums.
I think what you are doing is fine. Yes, the classes are tightly-coupled, but that is kind of the point -- you want to be able to reference only a single class to see all of your project-wide constants.
You do have to be diligent to ensure that ConstantsB contains only constants that are generalizable amongst all your projects, and ConstantsA contains only project-specific constants. If, later on, you realize that there is a constant in ConstantsB that you seem to be overriding in your subclasses a lot, then that's an indication it should've never been put in ConstantsB in the first place.
I think what you've got is a good first step. The next step is to gradually replace all references to ConstantsA.CONSTANT2 and ConstantsA.CONSTANT3 with ConstantsB.CONSTANT2 and ConstantsB.CONSTANT3 until you can remove the extends.
Most IDEs can be configured to show a warning if you refer to a superclass constant via a subclass, and I'd guess static analysis tools like FindBugs can do it, too.
One idea that might be slightly cleaner:
make all the constants classes interfaces
move all the constants out of ConstantsA and call it something like LegacyConstants
have LegacyConstants extend all the other, modular Constants interfaces
deprecate LegacyConstants
The goal would be not to have any inheritance between the Constants interfaces. LegacyConstants would be the only place there's any inheritance, it wouldn't declare any constants of its own, and when it's no longer used -- when every class that did use it instead refers to the proper Constants interface -- you've finished refactoring.
When you extract your constants, have the old class reference the constant defined in the new class. There's really no need to create an inheritance relationship here.
I could be wrong, but I don't think we need constants at all. It just means that you can't change the value of the constants and you probably should.

Categories

Resources