Applying static methods to data stored in a subclass - java

I'm working on a class to access information about a class library stored in a Jar file and run actions customized for each class library. It contains methods to load localized strings, etc. from the Jar file.
public class CodeBundle {
public static String str(String id) {
...
}
...
}
I need to be able to know which library I am trying to load information from, so I want to be able to use subclasses representing each library, for example:
public class JAppFramework extends CodeBundle {
...
}
So now in code that is part of the JApp Framework, I want to be able to call JAppFramework.str("...") to load a string from the JApp Framework resource bundle. And if I have another library, such as TestLibrary, I want to be able to call TestLibrary.str("...") to load a string from Test Library's resource bundle. What I did was have a method defined in CodeBundle called getFile() which would return the Jar file from which the library had been loaded. Then the str() method would use that to load the localized string.
The problem is that the static methods in CodeBundle can only access data stored in the CodeBundle class, not in any of its subclasses, as far as I know.
For various reasons, I can't use "getClass().getResource(name)" to load resources.
Is there any way to do what I'm trying to do?

You may try and use singletons:
public abstract class CodeBundle { // or even an interface
public abstract String str(String id);
}
public final class JAppFramework extends CodeBundle {
private static final CodeBundle INSTANCE = new JAppFramework();
// private constructor
private JAppFramework() {
// whatever
}
// get the instance
public static CodeBundle getInstance() { return INSTANCE; }
// Implement str() here
}
// Create other singletons as needed
In your code:
CodeBundle bundle = JAppFramework.getInstance();
bundle.str(whatever);
Of course, this is an ultra simplistic example. Put whatever fields/methods/constructors/constructor arguments are needed in CodeBundle -- which cannot be instantiated since it is abstract.

Related

Assign weaker access to method overriding from superclass

I have a Class called Module which has a Method onEnable();
Now i have a class called Config and want to make the onEnable(); method private because there is a predefined acting and a class extending Config should'nt be allowed to change the behaviour.
Is there any way to do this?
Example
class Module{
public void onEnable(){
}
}
A class extending Module which is allowed to use onEnable:
class HelloWorldModule{
#Override
public void onEnable(){
System.out.println("Hello, World!");
}
}
Now the config Class, where i want that onEnable is private so that Classes which extend Config cannot! Override onEnable:
class Config{
#Override
private void onEnable(){
}
}
So NOW, a class named ProgrammConfig which extends Config cannot override onEnable.
However, this is not working because you cannot override a public method to a private method.
By declaring a method as public, you are saying that it should be possible to call said method on every instance of this class, including subclasses. Declaring a method as private in a subclass doesn't make sense, and is thus not allowed.
Now, if you're concerned about subclasses overriding the method, you can declare the method as final to prevent this:
class Config extends Module{
#Override
public final void onEnable(){}
//Whatever
}
You cannot solve this using inheritance. If Config is a subclass of Module, then it must provide all functions of Module with (at most) the same access restrictions. Think of a subclass as a specialized version of the superclass: It can do everything the superclass can, likely more, but never less.
Still you can implement a Config class as desired. Just skip subclassing, and instead use a private field of type Module like so:
class Config {
private Module module;
public Config() {
module = new Module();
}
public int SomeFunctionFromModuleYouWantToExpose() {
return module.SomeFunctionFromModuleYouWantToExpose();
}
// ...
}

How do I make an instance available or accessible from anywhere in my android application

I'm new in android and I have a question.
I want to have just one instance of a class in my whole android program so that it's attributes won't change during the program, but I also want to call it's methods in all my activities.
With some search I realized that I can pass my object via implementing class as Serializable or Parcelable. I did this but I got following error:
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object
java.io.NotSerializableException: microsoft.aspnet.signalr.client.hubs.HubConnection
as you see one of my class attributes is HubConnection which is in microsoft package and i can't make it Serializable.
What can I do to pass the object of SignalR class to another activities? And what are my options?
public class SignalR implements Serializable {
private HubConnection connection;
private HubProxy proxy;
//some methods
}
If you want a single instance of YourCustomClass throughout the application, you can do by keeping a reference of your custom class object in YourApplication class.
Create a class and extends it to Application class. Create setter and getter method in your application class to access the your custom class instance. Now you can access the your custom class instance from any where within your app and you don't have to pass the instance between activities.
public class YourApplicationClass extends Application{
private YourCustomClass yourCustomClass;
public YourCustomClass getYourCustomClass() {
if (yourCustomClass == null) {
yourCustomClass = new YourCustomClass();
}
return yourCustomClass;
}
public void setYourCustomClass(YourCustomClass yourCustomClass) {
this.yourCustomClass = yourCustomClass;
}
}
Don't forget to put android:name="YourApplicationClass" in your manifest file.
<application
......
android:name=".YourApplicationClass"
....... >
Now to access the object from your activity, say MainActivity you would write something like -
#override
protected void onCreate(Bundle savedInstanceState) {
YourApplicationClass app = (YourApplicationClass) getApplication();
YourCustomClass yourCustomInstance = app.getYourCustomClass();
}
If your goal is to have a single instance of your class globally accessible from all your activities, you do not want to be passing it around with bundles. Rather use a singleton pattern.
If you do need to use the bundles for some other reason, use Parcelable instead of Serializable, it is meant to be faster. There is a pattern to follow with creating a parcelable. Your best bet is to copy-paste the answer from here, and change the constructor, parcelling, and unparcelling.

Creating and initializing class with default values

While working on an web-application , I need to get a set of classes at few steps and I am thinking to separate this logic to a simple Factory so as based on the Class type We can create class instance as well init it with default values.
Current structure of Class hierarchy is
public interface DataPopulator<Source,Target>{
// some method decaration
}
Abstract class
public abstract class AbstractDataPopulator<Source,Target> implements DataPopulator<Source, Target>{
// some common implimentation
}
And now classes which will be used as actual implementations like
Type1Populator extends AbstractDataPopulator.
Type2Populator extends AbstractDataPopulator.
Each of these implementation needs a set of common dependencies based on what functionality is being executed by those Populators.
As of Now I am creating instance with new and than filling those dependencies with simple setter methods.
I am thinking about creating a simple factory pattern like
public interface PopulatorFactory{
<T extends Object> T create(String className) throws Exception;
<T extends Object> T create(Class populatorClass) throws Exception;
}
Abstract class
public abstract class DefaultPopulatorFactory impliments PopulatorFactory{
public <T> T create(final Class populatorClass) throws Exception{
return Class.forName(populatorClass);
}
// other method.
}
Implementation classes
public Type1PopulatorFactory extends DefaultPopulatorFactory {
public <T> T create(final Class populatorClass) throws Exception{
final T populator= super.create(populatorClass);
}
}
I also want to initialize newly created instances with some default values specific to each implementation, but I'm not sure what's the best way to do this?
Should I define another method say initDefaults?
What is the best way to pass those dependencies to these poulators.
Is the approach outlined by me fine or is it overly complicated?
In cases when you are building not-so-trivial objects it is usually better to use the Builder pattern instead of a Factory.
In your case if you don't need external data sources you can simply write constructors for your classes where you can supply the default values and get rid of the contraption in your question.
If you use the Builder pattern you can simplify your framework by using a Builder object for the common data and a SomeOtherBuilder which extends from Builder and adds the custom values of the specialized implementation. You can make your classes constructors which are taking a Builder object.
public class Builder {
// your fields go here
}
public class SomeOtherBuilder extends Builder {
// your specialized fields go here
}
public class YourClass {
public YourClass(Builder builder) {
// construct it here
}
}
You can also make your classes generic with using something like T extends Builder.

Refactoring static class so I can unit test it

I have a static class that I would like to refactor so I can change the name of the properties file etc., and to be able to unit test it easier.
Current I have this:
public enum MySettings {
INSTANCE;
//priv vars
private string applicationUrl;
private MySettings() {
MappingJsonFactory jf = new MappingJsonFactory();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream mySettingsInputStream = classLoader.getResourceAsStream("a.properties");
Properties mySettingsProperties = new Properties().load(mySettingsInputStream);
// code below to load json and set priv vars etc.
}
public String getApplicationUrl() {
return applicationUrl;
}
}
How could I set the name of the properties file to something else in my unit tests?
"Inversion of control." The simplest way to do this here would be to take it in as a constructor arg. At the higher end would be an IOC framework, such as Spring.
Worse case since you're dealing with an enum - may need to factor out an interface then provide an implementing enum. Or better:
public enum Settings {
PRODUCTION("prod.xml"), UNIT_TESTING("dev.xml");
//...
you could fiddle all the stuff from the enum class into a real instantiable class (via package protection or protected) and then make an instance of it accessible via the enum (getter). Like this you can unit test everything like a charm and also have it as a singleton :). With this you don't need a second Enum constant (as pointed out in the comments).
If you are using protected instead of package protection you can unit test it by creating a dummy class that inherits from the actual class and instantiate it in the test like this:
private static class Dummy extends NewClass {
public Dummy() {
super();
}
}

Java newbie problem: package with private access

Pack.java imports pack.TestPack; but it cannot access it. I cannot understand why it cannot access the class despite the import.
Error
Pack.java:7: TestPack() is not public in pack.TestPack; cannot be accessed from outside package
System.out.println(new TestPack().getHello());
^
1 error
Pack.java
import pack.TestPack;
import java.io.*;
public class Pack
{
public static void main(String[] args){
System.out.println(new TestPack().getHello());
}
}
TestPack.java
package pack;
import java.util.*;
import java.io.*;
public class TestPack
{
private String hello="if you see me, you ar inside class TestPack";
public String getHello(){return hello;}
TestPack(){}
}
You should make TestPack's constructor public.
public class TestPack
{
private String hello="if you see me, you ar inside class TestPack";
public String getHello(){return hello;}
public TestPack(){}
}
The thing is, even though TestPack visibility is public, its parameterless constructor visibility is package (which is the visibility when you don't specify one explicitly).
package visibility means that classes in the same package will be able to see it. Since TestPack and Pack are not in the same package, Pack can't call TestPack's constructor.
In the way you are using getHello function, you may start thinking using static methods
public class TestPack
{
private static String hello="if you see me, you ar inside class TestPack";
public static String getHello(){return hello;}
private TestPack(){}
}
then you just will do:
public class Pack
{
public static void main(String[] args){
System.out.println(TestPack.getHello());
}
}
I suggest that you don't make the class public but make the constructor public and have folks use a public interface that your class implements. It is a good idea to start the API to your package to be public interfaces (and perhaps some public abstract classes) and hide your implementation classes by not marking them as public so that you can change these over time. You can then provide a public factory methods in your package which instantiate your package private class and return them as the interface types. Here is an interface which is public:
package stackoverflow;
public interface Widget {
public void doWidgetWork(String work);
}
Here is the implementation which is "package private". The compiler wont let code outside of the same package import nor use this class at all:
package stackoverflow;
/*package*/ class WidgetHidden implements Widget {
public WidgetHidden(String configOptionA, String configOptionB){
// ...
}
public WidgetHidden(){
// ...
}
public void doWidgetWork(String work)[
// ...
}
}
notice there that the second occurrence of the word /package/ is a comment (it is not legal in java to use that word there) but many programmers use such a comment in that position to show people that it was not an accident that the class is not public; it signifies that the developer really intended that the class is deliberately "package private". To let people instantiate the class from outside of your package you provide a static factory class (else an instance factory class):
package stackoverflow;
public class WidgetFactory {
public static Widget newInstance( String configOptionA, String configOptionB) {
return new Widget( String configOptionA, String configOptionB);
}
}
The whole point of the factory class is that it hides your internal classes (the ones you hide as package private). Over time you can change your factory classes to return new classes or rename or delete the WidgetHidden class.
Many frameworks indicate which classes other developers should not use by putting them into a package with the name "internal" in it. The public interfaces would be in the main package (e.g. "com.stackoverflow.widget") and the hidden classes into your internal package which only exposes public factory classes (e.g. "com.stackoverflow.widget.internal").
A variation on the theme is to not use a static method on the factory class; make it a regular method. The alternatives are called "static factories" or "instance factories" depending on whether the method is static or not. Not making the method static seems like more work for people using your package as they first have to instantiate your factory object before using it to create Widget. Where is helpful is when people might want to set some defaults for all widgets on the constructor of the factory then use the none static newInstance methods to specify anything beyond the defaults:
public class WidgetInstanceFactory {
private String defaultOptionA = null;
public WidgetInstanceFactory( String defaultOptionA ) {
this.defaultOptionA = defaultOptionA;
}
public Widget newInstance( String optionB ) {
return new WidgetHidden( this.defaultOptionA, optionB );
}
}
It is possible to get around package private protection using reflection to find and invoke the constructor. A really nice feature of the Spring framework it that it will instantiate classes that are not public even when there is no factory class (although it is more polite to provide factory classes which Spring is happy to use also). The following code will work:
package stackoverflow.other;
class TestInstantiate {
private Widget myWidget = null;
public TestInstantiate(){
this.myWidget = instantiatePackagePrivateClass("stackoverflow.WidgetHidden");
}
private Widget instantiatePackagePrivateClass(String className)
throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
#SuppressWarnings("unchecked")
Class<FileUploadSequence> clazz = (Class<Widget>) Class.forName(className);
Constructor<Widget> constructor = clazz.getConstructor(new Class[]{});
constructor.setAccessible(true);
Widget widget = (Widget) constructor.newInstance((Object[])null);
return widget;
}
}
In that example I used the no arguments constructor but clearly you can find and invoke the two string constructor using the same approach. Clearly such code gets around the intention of the programmer who wrote WidgetHidden; they wanted to hide it as they are likely to change it. Anyone who uses such a back door to manipulate the package private object should be aware that the class WidgetHidden is not part of the public API of the framework they are using so it likely to be deleted or changed without prior notice by the developer who wrote the package you are using. Renaming it to be WidgetInternal and putting it into an "internal" package make it every more the case you are telling people "do not uses". The JVM has optional security setting which prevent people from doing such tricks; but the person running the JVM has to configure it externally to dis-allow such tricks which is only useful when you want to run someone else code you don't trust and prevent it from pulling such tricks.
The book Effective Java by Josha Block 2nd Edition has a lot of discussion and examples and details of the pitfalls when trying to write a good API. It has a lot of detail to explain why you should always look to hide as many classes as you can with lots of other good "tricks of the trade".

Categories

Resources