Accessing static field avoided by referencing Class? - java

I'm not understanding why this is working, please help educate me.
Config CFIG = new Config();
Tile selectedTile = CFIG.tileGallery.get(1);
System.out.println("This is the name:" + selectedTile.getName());
Feature selectedFeature = CFIG.featureGallery.get(3);
System.out.println("This is the name:" + selectedFeature.getName()+
" " + selectedFeature.getEffect(0));
I initialize the object CFIG, which sets both the member variables of the Class Config tileGallery ArrayList and featureGallery ArrayList. When I run the code, it works, outputting the selected test values. However for both of the declarative statements Netbeans gives a warning of "Accessing static field "
Using the hint of "Replace with class reference", it changes the statements to:
Tile selectedTile = Config.tileGallery.get(1);
Feature selectedFeature = Config.featureGallery.get(3);
When I run it, it still works!
Question, Config. isn't identifying which Config object to call data from. Now I only have a single Config Object in existence, but even if I initialize a second Config object it still doesn't appear confused.
What's going on here?
EDIT: andih wondered what the code of the Config Class. I didn't add it, because it wasn't much, and figured you could easily assume what it did as it pertains to the issue. However, here it is, just in case.
public class Config {
public static ArrayList<Tile> tileGallery;
public static ArrayList<Feature> featureGallery;
public Config (){
this.tileGallery = Tile.ReadTileXML();
this.featureGallery = Feature.ReadFeatureXML();
}
}

The static keyword means this field belongs to the class than instance of the class. Even if you create hundred objects , this field will be shared amoung them.
These static fields "tileGallery" and "featureGallery" from each instance will be pointing to same object in memory.
The static variable gets memory only once in class area at the time of class loading.

Without the exact code of your Config class it's hard to say but it looks like your Config class uses static fields like
public class Config {
public Config() {
titleGallery = new ArrayList();
titleTallery.add(new Title());
}
public static List<Title> titleGalery;
}
That's what the hint says.
In this case all your Config instances share the same titleGalery and you can access them via Config.titleGalery.
If you want different Configinstances with different value you'll have to remove the static keyword to get independent instance fields.
public class Config {
public Config() {
titleGallery = new ArrayList();
titleGallery.add(new Title());
}
// old: public static List<Title> titleGalery;
public List<Title> titleGalery;
}

Related

Is this a proper way to share variables among many objects without a singleton?

So, I have a program where many objects of several different classes need to read some (many) variables from an object of 'class X', to give it a name. A quick and simple way of doing this would be to make a singleton, which wouldn't be X itself but a class it access to. I've done this, and later on it started feeling dirty, and many seem to agree, so I'd like to change my design for this. I haven't found any ideas to replace this pattern, though, just "don't do it" and "pass the data around." I'd like my data to be read-only, though. I haven't found mention of any other patterns.
The best I've got to share these read-only variables, which seems perfectly fine to me, is to have a class SharedVars for the data to share, but in the form of an inner class. It's inside Data, which is an outer class that is able to modify SharedVars, encapsulating what's meant to be read-only for the other classes. Basically, any class that wants to read these variables needs a Data.SharedVars object:
public class Data {
public static class SharedVars {
private int encapsulatedData;
public int getData() {
return encapsulatedData;
}
}
// no one should touch this but Data:
static private SharedVars sharedData;
Data() {
sharedData = new SharedVars();
}
public SharedVars getDataRef() {
return sharedData;
}
// here's where this class (and only this class, whenever it's told)
// modifies the encapsulated data:
void manipulateData() {
sharedData.encapsulatedData = 5;
}
}
One of the classes that depends on this would take this form:
public class Client {
// This class can't access the data directly
// so it'll use Data's getter:
Data.SharedVars vars;
public Client(Data.SharedVars vars) {
this.vars = vars;
// vars.encapsulatedData = 5; // is not allowed, since the field is private (which is what I want)
}
public void go() {
// the proper way to get its hand on the data:
int data = vars.getData();
System.out.println("The data is " + data);
}
}
Main is not needed in this example, but I'll leave it here anyway:
public class Main {
static Data dataControl;
static Client client;
public static void main(String[] args) {
dataControl = new Data();
client = new Client(dataControl.getDataRef());
dataControl.manipulateData();
client.go();
}
}
Is this proper? Or, what are the risks here? Notice I don't want the objects to copy them for themselves, since they'll be changing all the time, and I don't entirely like the idea of having a reference to the 'class X' I've mentioned before.

How to get a list of all implemented classes in Strategy Pattern?

I want to design a system that allows the user to select from a list of file types to save the file as. I have a class named Word, and an interface named SaveFileType. Every filetype implements SaveFileType which has a saveFile() method. The idea is that when the 'programmer' wants to add a new filetype, none of the code in the application has to be changed.
This is the UML diagram I have made:
The problem that I am facing is the Word class doesn't have the list of all available file types, that I need to display to the user.
Some sample code below:
Word class:
public class Word {
SaveFileAs saveFileAs;
Document currentDocument;
public Word(Document currentDocument) {
this.currentDocument = currentDocument;
}
public void saveFile() {
// Print all available filetypes
// No actual file-saving logic is needed.
}
}
Word97 Class:
public class Word97 implements SaveFileAs {
#Override
public void saveFile(Document currentDocument) {
// Do some Java wizardry here.
System.out.println("Document named '" + currentDocument.getTitle() + "' has been saved as filetype 'Word97' " );
}
}
Main class:
public class Main {
public static void main(String[] args) {
Document notes = new Document("Notes", "This is a note.");
Word wordProgram = new Word(notes);
// saveFile should print out a list of all possible filetypes.
wordProgram.saveFile();
}
}
Strategy is for changing implementation at runtime, you cannot get all implementations. It would be the task of another class. Also you need somehow a method like setStrategy(Strategy) in your Word class, that's why you've chosen the pattern right?
For get all implementations, you could make use of ServiceLoader. I would add an enum in the picture.
So the example codes look like:
method in Word class:
void setSaveFileStrategy(AvailableStrategy strategy){
this.saveFileAs = strategy.strategy();
}
The enum:
enum AvailableStrategy{
Word97( Word97.class),
//.... once new strategy was introduced, you need add an entry here.
WordXml( WordXml.class);
private Class<saveFileAs> strategyClass;
AvailableStrategies(Class<saveFileAs> strategyClass) {
this.strategyClass = strategyClass;
}
saveFileAs strategy() throws IllegalAccessException, InstantiationException {
return strategyClass.newInstance() ;
}
}
I think you know how to get all enum instances (available strategies).
Note that codes were not compiled and tested, just for showing the idea. Exception handlings were ignored.
It would be bad if the Word class knew about all the types. It's the job of another class, even if word uses it. One solution would be to have a new class that maps a string extension to the strategy. And can enumerate those strategies:
public final class DocumentTypeMap implements Iterable<SaveFileAs> {
private final Map<String, SaveFileAs> docTypes = new HashMap<>;
public void register(String extension, SaveFileAs saveFileAs) {
docTypes.put(extension, saveFileAs);
}
public Iterator<SaveFileAs> iterator() {
return docTypes.values().iterator();
}
}
Usage:
DocumentTypeMap map = new DocumentTypeMap();
map.register(".doc", new Word97()); //etc.
Word word = new Word(map); //inject the dependency of a pre-configured map into the word class.
Then when the Word class needs the correct strategy during saving, it can use a method on DocumentTypeMap (not provided here) to get the correct one. I'm thinking that might be by extension.
If you want to be able to add a document type without changing any code, it means that the document type list has to be defined outside your code, in file like a property file and your code has to read the property file to know all available types.
Then you need to add in this property file which class implements how to save a specific document type and you implement a factory which instantiate a class given its name, and a class which associate the right instance according to the chosen type.
For the properties files, you can have entries like:
ext_1=.doc
ext_2=.xml
ext_3=.rtf
class_1=Word97
class_2=WordXML
class_3=RTF ...
A such file is easy to parse to know the types list and which class has to be used to save a document.
To know how to instantiate a class from its name, see the class Class and the method newInstance.
This is an "old way", maybe with injection is there a most up to date solution.
In your UML model, I would add the class which reads the properties file, the class which instantiates a class from its name, and the class which associate the right instance to Word. To model the properties file, maybe an instance objet may be use since a properties file is an instance of ResourceBundle.

Apache BeanUtils behavioral conflict while copying List items from different classes

I am developing an application that copy data of one class to another class.
I am trying to test getter-setter method works fine or not. To improve test coverage I am making some class and methods that will use podamfactory to fill up data inside given class's members.
Then I am copying data of that object to other object using apache BeanUtils.
Then I am asserting both objects to check that both have same data or not !
The problem I am facing that:
I have create 3 classes:
Starter.java [have main method to run application]
ChildClass.java [have only 1 member i.e. Collection of String and it's getter method and add method to add data inside that member]
ParentClass.java [inside this class ChildClass's instance have been created and instantiated and related getter and setter method. Also have hashcode and equals method]
Code:
public class Starter {
static final PodamFactory factory = new PodamFactoryImpl();
public static void main(String[] args) throws Exception {
System.out.println("Start");
testClasses(ParentClass.class);
System.out.println("End");
}
public static void testClasses(final Class<?> klass) throws Exception {
final Object source = factory.manufacturePojo(klass);
final Object destination = klass.newInstance();
BeanUtils.copyProperties(destination, source);
Assert.assertEquals(source, destination);
Assert.assertNotEquals(source, new Object());
Assert.assertEquals(source.hashCode(), destination.hashCode());
}
}
In Main method I am passing ParentClass to check it's getter setter. testClasses method do the main work of copy and assertion.
When I am debugging I found that after copying properties of class, child class's instance have list and that have 5 members. In both object there's 5 members in List element.
But When I am passing ChildClass in Main then try to debug I am getting 5 element in source and in destination class it have 0 element after copying properties.
So I don't understand this behavior of BeanUtils, what need to do If I want same work when I am passing ChildClass in Main ?
When I am passing ParentClass it's have different behavior and when I am passing ChildClass it have different behavior in Copying properties.
I have created GitHub Repository to show my code. You can access and check code of my application.
I have created simple gradle project for dependency management.
If anyone knows more about it then let me know.
Thanks.
BeanUtils follows strict definition of properties in Java Bean sense, i.e. each property must have getter with name get + name of a field and setter with name set + name of a field. While your child class contains no setFields() setter. In other words you could change it like this
public class ChildClass {
private final List<String> fields = new ArrayList<>();
public List<String> getFields() {
return this.fields;
}
public List<String> setFields(List<String> fields) {
this.fields = fields;
}
}
or alternatively
public class ChildClass {
private final List<String> fields = new ArrayList<>();
public List<String> getFields() {
return this.fields;
}
public List<String> setFields(List<String> fields) {
this.fields.clear();
this.fields.addAll(fields);
}
}

Get name of class during static construction

In C# I can assign the name of a class to a local static variable like this.
public class MyClass
{
private static string TAG = typeof(MyClass).Name;
}
I've found this very useful, because the value of the string automatically updated if the class is refactored to another name. Handy for tagging debug messages and such.
Is something like this possible in Java?
public class MyClass
{
private static String TAG = ????;
}
I know I could use getClass().getName() but that requires a reference to an object. Is there a way to do this on a static variable?
You don't need to assign the name of a class to field instead of writing.
MyClass.TAG
you can write
MyClass.class.getName();
If you really need to you can assign this to TAG but I don't see the point.
A trick is also available that does not require programmer's knowledge of the class name beforehand:
public class MyClass
{
private static String TAG =
new Object() { }.getClass().getEnclosingClass().getName();
}
This trick uses a nested anonymous Object subclass to get hold of the execution context. It has a benefit of being copy/paste safe in case of cloning your code across different classes...

Java - Class type from inside static initialization block

Is it possible to get the class type from inside the static initialization block?
This is a simplified version of what I currently have::
class Person extends SuperClass {
String firstName;
static{
// This function is on the "SuperClass":
// I'd for this function to be able to get "Person.class" without me
// having to explicitly type it in but "this.class" does not work in
// a static context.
doSomeReflectionStuff(Person.class); // IN "SuperClass"
}
}
This is closer to what I am doing, which is to initialize a data structure that holds information about the object and its annotations, etc... Perhaps I am using the wrong pattern?
public abstract SuperClass{
static void doSomeReflectionStuff( Class<?> classType, List<FieldData> fieldDataList ){
Field[] fields = classType.getDeclaredFields();
for( Field field : fields ){
// Initialize fieldDataList
}
}
}
public abstract class Person {
#SomeAnnotation
String firstName;
// Holds information on each of the fields, I used a Map<String, FieldData>
// in my actual implementation to map strings to the field information, but that
// seemed a little wordy for this example
static List<FieldData> fieldDataList = new List<FieldData>();
static{
// Again, it seems dangerous to have to type in the "Person.class"
// (or Address.class, PhoneNumber.class, etc...) every time.
// Ideally, I'd liken to eliminate all this code from the Sub class
// since now I have to copy and paste it into each Sub class.
doSomeReflectionStuff(Person.class, fieldDataList);
}
}
Edit
I picked the accepted answer based on what applied best to my problem, however it seems to me that all three of the current answers have their merits.
No, it's not possible without grabbing the stacktrace (which is imo nastier than your initial approach and for which I would in any way prefer Thread#getStackTrace() above new Exception()).
Rather do that job in a non-static initializer (or the default constructor) of the abstract class where you check the initialized status.
public abstract class SuperClass {
{
if (!isInitialized(getClass())) {
initialize(getClass());
}
}
}
The called methods in turn can be safely static.
yes, I use this often to initialize a static Log variable :
e.g. :
public class Project implements Serializable, Cloneable, Comparable<Project> {
private static final Logger LOG = LoggerFactory.getLogger(Project.class);
...
To get a class at runtime, you could do something along the lines of
public class Test {
public static void main(String[] args) {
try{
throw new Exception();
}
catch(Exception e){
StackTraceElement[] sTrace = e.getStackTrace();
// sTrace[0] will be always there
String className = sTrace[0].getClassName();
System.out.println(className);
}
}
}
Not pretty but will do the job (ripped from http://www.artima.com/forums/flat.jsp?forum=1&thread=155230).
This means you still make a call from the subclass (so is in the stack trace), but you don't need to include the XXX.class as an argument.

Categories

Resources