As good as the Java API is, I need to change the code of some classes in the default API packages (for example java.util.Scanner) for a project I am working on.
Ideally, I would extend the classes I am interested and create my own sub-classes, but the classes I want to extend are declared 'final'. How do you suggest I do this? Will I get into trouble with the compiler if I customize the source code of these packages?
If you can, you should rather wrap and delegate, as suggested in another answer. See the Adapter Pattern.
But there are of course ways to do this if you really need it.
A straightforward approach is to simply modify the code in downloaded sources and substitute your own version of a jar in the classpath.
Another option is to use aspect-oriented programming techniques, likely with AspectJ to intercept and modify calls as needed.
It might also be possible to hack together a solution using reflection and home-grown classloaders, but it will be painful to code.
All of these are however quite risky if you don't know what you're doing. Frequently classes are made final for good reason.
If you tell us more specifically what it is you're hoping to change, we might be able to provide assistance in avoiding what you currently think you need.
you really cant extend a final class..
if u really want to add a functionality by extending a class you can do it by modifying class src. from JDK and save it as your own class and use it.
Don't do that. Write your own code which wraps around the original scanner and use that. To update internal packages, there is an endorsed directory property which you can provide at runtime.
Never do it! Never change core classes. If class is final - use composition not inheritance.
Related
I am using an open source framework (libGDX to be exact), however I want to edit internal behavior of one class and use the rest of the framework as is. The problem is, that I cannot access protected members of that class when I extend it. I do not know if reflection is the best thing for game. The class is used in the other classes of the framework and I want to use them too.
EDIT: found out that the members were only protected (original question included private members), but I was not able to access them outside the package
Three options:
you suggest a patch to the community behind that library. Try to convince the owners to change their code - so that your problem can be addressed in reasonable ways
you create your own private fork. It is open source!
yes, you might be able to use reflection. This one comes last because reflection is easy to get wrong and breaks as soon as somebody starts using security managers - or when the library owner make changes such as renaming classes or fields. See here for more detailed information.
use inheritance, you have to create package inside your project matching the target class package name. Create child class there so you can access protected members.
I think it is obvious which option would be better for you - although initially it means more work to convince people that your idea has merit.
Alternatively you might ask yourself if your idea is really a good idea. Maybe you just don't understand how to use that library properly? But we can't help with that given your current input...
Background: I notice that in many projects almost all classes in the internal code are public and not final, even if they don't need to be. However, it seems sensible to me to make this decision not by default, but only make classes public if they are actually meant to be used from other parts of the system. Having package protected classes is an easy mechanism to enforce boundaries between modules, and serves as a documentation on the intended use of a class.
If there was a (preferrably free :-) tool to protect all classes that can be protected without breaking the program, and maybe make everything final that has no subclasses, that would be a good starting point to start a conscious use of protection mechanisms. (Of course you need to tweak things afterwards.) Do you know such tool?
Caveat: I am aware that there are better modularization mechanisms like OSGI and the planned superpackages and so forth. But in many current projects this is not an option, and using the plain old Java mechanisms is something you can easily do. Also, this works only if you have shared code ownership (such that everybody can change things back to public as needed) and if you are developing an endproduct, not a library for use by others. I am also not too sure about the benefits of making things final - this prevents AOP and mocking.
CLARIFICATION: As I said, I am not talking about libraries that are thrown over the fence to someone who can't change it, but about internal code of medium sized projects where everybody is encouraged to change and refactor everything as needed. When I am talking about package protected or final think of it as "protected until someone feels a compelling need to lift those restrictions". If someone feels the need to lift the restrictions set by the tool, he is welcome to do so.
Even if there was such a tool, (there isn't), a good programmer wouldn't use it... access specification is a design issue best understood and settled by the programmer himself. Think about it... you make a program and run the tool and get everything sorted (Assuming the tool is super-intelligent in the first place to actually understand your program).. then you decide to modify it... extend some classes, etc.. and you end up extending final classes and making objects of private classes.. (and these are few of the many problems you'll face)...
Thing is.. when the tool does its job, you would no longer even understand your own program.
Bottomline.. stop looking for tools to solve your design issues.. (its like asking for tools that will automatically debug your program)
You can have a look at ATL from Eclipse. Although ATL is used to create model to model transformations between different kinds of models, there is no restriction that source and target model are not of the same type. You could create a transformation from Java to Java that makes your current classes protected or final. MoDisco is a toolset of Eclipse makes use of that, just if you want to see examples.
In software development we are all using the libraries by software providers. Consider in class A there are four functions viz., x,y,z. I just want my development team to avoid using the function x. So instead of telling them not to use, I found an idea. Inherit the class and override all the functions and for the function x an unsupportedmethod exception is thrown and for the rest I'm calling the super methods. There also I found a problem, developers can use the base class A directly, how to avoid the class A being used directly. I found a similar functionality in OSGi, the lib bundles can be brought in and then not exported and so on. Is there are any way to achieve this is java?
I suppose code reviews exist for these reasons. Consider situation where you can not edit the source of a third party, what would you do ? Like Siddharth says, sub class it and throw a meaningful exception and document it with a clear reasons. If someone is using base class even after that, mostly it may not out of ignorance,but it may out of curiosity. That kind of thing can be appreciated personally and for learning, but for the project sake developer has to follow the guidelines.
I think simply telling your developers what to do is preferred over a complex software solution. Sometimes the simple thing is better.
But, if you insist on going down this path, you can enforce your architecture standards using aspects if you're a Spring user. Weave the offending methods with an aspect that throws an exception if they're called.
You can edit library class file in hex editor and modify its access modifier from public to package private. Also you can rename it and then use inheritance to wrap this class. Here you can find class file specification. Once I've tried this technique to substitute jdbc driver class with wraper class that provide some additional logging and other useful tricks.
There is a variety of tools that check source code for adherence to certain rules, such as formatting, dead code, naming conventions for variables etc. Popular ones for Java include the Maven Enforcer plugin, checkstyle and PMD.
These might allow you to write a rule that forbids certain method calls. Then you could check automatically at compile time. As far as I can tell, unfortunately none of the tools above support "illegal method calls" out-of-the-box; however, at least for PMD writing new checks is fairly simple.
Is it possible to import and use two different classes with the same name and package in java?
For example, let's say I have two classes named "com.foo.Bar" that are slightly different. I'd like to be able to use both, but I have a restriction (because of stupid reflective crap) that forces me to keep the names and packages the same.
Is there some feature of java that would allow me to import and isolate each of these classes?
To elaborate, I changed my avro schemas in ways that they shouldn't have ever been changed (oops!) and now I'd like to go back and change the old avro files that can't be read with my new schema into files that can be read by my new schema. Avro seems to force you to use a specific class and package name to load the files.
Yes there is. You would need to implement your own Classloader and play some games to be able to access both during runtime.
I'm sure this is possible, because I ran into a very hard to debug issue where someone had a weird Classloader in their product that was messing up loading libraries and providing 2 different versions of the same file from 2 different versions of the library.
However, this sounds like an INCREDIBLY bad idea. I'd go back and find a different way of fixing your issue. This will only bring you heartache in the long run. Heck, it probably already is, as you investigate class loaders.
EDIT: To be specific, you cannot "import" both. But you can access both at runtime.
No, java packages are used precisely to avoid that problem.
Yes it is. It does require you to make your own ClassLoader, though
I had made a demo of that on github to!
If you really most definitely must do something like this, you can achieve it by using different classloaders and possibly reflection.
This is not the way Java works and it's not allowed on purpose - you shouldn't be doing stupid things which will screw up things for you.
There are no namespaces in Java, only in C#, so I assume you mean packages. There can only be one fully qualified name per project.
Technically it can be done using some low-level trickery such as rewriting the byte-level code. As far as I know the different java crypter/encrypters work like that - they have a lot of classes called A.class B.class C.class etc.
It sounds to me like you need to define your method signatures in an interface called com.foo.Bar. Then provide two different concrete implementations of the interface (say, com.foo.DefaultBar, and com.foo.SpecialBar). This way, you can program against the interface type, and switch between the two different implementations as required.
Can you elaborate on what you mean by "reflective crap"? That may provide insight into your exact issue.
Don't mess with the class loader or any other low level trickery. The best way to solve such issues it to have a clear design in the first place that anyone can understand.
As already mentioned writing your own Classloader or additionally use a OSGi framework like Equinox which does the classloading for you
I have a very quick question - Is it possible to modify the source code of Java API e.g. Junit, JABX ?
I know it seems a very stupid question, but it has been bugging me for a while.
If you can get your hands on the source, then sure you can modify it. It might not be the best option. It might be better to just create subclasses (if possible) and overwrite implementations, and use your subclasses. Or use composition to proxy the library classes. Depends on what you need to do/fix.
Keep in mind if you modify the source of an external library, and upgrade, you have to modify the source again. You might have to change your extensions/proxies as well if you go that route, but experience has taught me that's typically less complicated.
for open source API such as JUnit: yes