Well, I've a final property but I don't want to initialize it when I create my object because I can't. So I tried to not initialize it in my constructor but using a setter, I guessed it would have been something like a only-one-time usable setter, but I've this error :
Test.java:27: error: cannot assign a value to final variable foo
this.foo = new String(foo);
Here is a short code I used to test this :
class Test {
private final String foo;
public static void main(String[] args) {
Test test = new Test();
test.setFoo("gygygy");
System.out.println(test.getFoo());
}
public Test() {
System.out.println("Constructor");
}
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
So I assume the constructor implicitly makes something like this.foo = new String(); or this.foo = null; and I think I can't modify this behavior, but how can I have an equivalent to what I wanna do ? I think in something like :
private String foo;
/* ... */
public void setFoo(String foo) {
if( !(this.foo.isInitialized()) )
this.foo = foo;
}
but the Object.isInitialized() method obviously doesn't exist, and I can't find an equivalent x)
So here's my question in a few words : How can I do ? I want a final attribute that is not initialized at the instantiation of the object.
Thanks !
You can add a boolean field isInisialized but the best option is to pass the value in the constructor (possibly using a Builder pattern if you need to)
So here's my question in a few words : How can I do ? I want a final attribute that is not initialized at the instantiation of the object.
You simply can't do that. All you can do is have a separate field which you also update to note once you've set the "real" field - and if you try to set it a second time, throw an exception.
Alternatively, make your type immutable, but give it a method which constructs a new instance of the class, with the same data as before except the single new value, e.g.
public Test withFoo(String newFoo) {
// Call a private constructor here, passing in the other fields from
// "this", and newFoo for the value of foo
}
Rule says a final instance member variable should be initialized at the very place where it is declared or within the constructor. By this rule, your requirement cannot be satisfied with your piece of code as is. You can use a builder pattern to achieve it. See this link Builder Pattern in Effective Java
Related
I'm learning Enum concept in java and I faced a problem while practicing.
Here is the code snippet,
public class MyClass {
private String cardColor = CARDS.SPADE.cardColor; #Causes Null Pointer #Default Value
private MyClass(CARDS card){
this.cardColor = card.cardColor;
}
public static enum CARDS{
SPADE("Black"),
CLUB("Black"),
DIAMOND("Red"),
HEART("Red");
private String cardColor = null;
private MyClass obj = null;
CARDS(String color){
this.cardColor = color;
obj = new MyClass(this); #Trying to create object for MyClass
}
public String getCardColor(){
return this.cardColor;
}
}
public static void main(String args[]) {
System.out.println(CARDS.SPADE);
}
}
I'm trying to create a MyClass object private to the enum in it's constructor. Here the value CARDS.SPADE is null and I end up with Null Pointer Exception.
If I don't create an object in enum constructor everything works perfect,
obj = new MyClass(this);
I'm not understanding why the static enum is not initialized and I'm confused with the control flow here. Can someone explain me what's wrong here?
You have a circular dependency : the initialization of the CARDS enum and the MyClass instance depend on each other.
CARDS constructor instantiates MyClass but MyClass constructor relies itself on the CARDS.SPADE state that is not still fully initialized as in the pending enum constructor.
Either break this cycle or do things in two times. Init the enum without the bidirectional relationship and after the constructor invocations, set the enum value to the MyClass instance via a setter.
Note that the "real" cause of the NullPointerException is that you don't refer to the currently instance created in the enum constructor (this) but you refer the enum value from the enum class itself : MyClass.CARD.SPADE.
The first has a state but the second not yet since the enum constructor has not returned yet.
By passing the enum instance into the constructor of MyClass it will "work" :
CARDS(String color){
this.cardColor = color;
obj = new MyClass(this);
}
}
// ...
public MyClass(CARDS cards){
cardColor = cards.cardColor;
}
But in a general way, passing this during constructor body to another object/class not a good idea. This may leak to an inconsistent state if the object states changes between this time and the end of the constructor invocation.
To clarify this, consider the following code:
public class Foo {
private Object thing;
public Foo() { ... }
public Object getThing() {
return this.thing;
}
}
public class Bar {
public Bar() { ... }
public Object makeNewThing() { ... }
public void changeThing() {
Foo foo = new Foo();
Object thing = foo.getThing();
thing = makeNewThing();
}
}
When Bar mutates modifies the value of the Object it receives from foo.getThing(), is the original private member within foo mutated modified?
edit: some words
is the original private member within foo mutated?
No, because you are assigning something new to the variable thing in changeThing, not mutating the object. If you did mutate the object, the mutation will reflect in the private member as well.
Note that getThing will return the original object referenced by Foo.thing, not a copy of it.
Since in your code, thing is of type Object, this behaviour is a little hard to see. I will use a mutable class Baz to demonstrate this:
public class Baz {
public int x = 0;
}
public class Foo {
private Baz thing;
public Foo() { thing = new Baz(); }
public Baz getThing() {
return this.thing;
}
}
public class Bar {
public Bar() { ... }
public Object makeNewThing() { ... }
public void changeThing() {
Foo foo = new Foo();
Baz thing = foo.getThing();
thing.x = 10;
System.out.println(foo.thing); // this will print 10, not 0
}
}
So to avoid any modifications to Foo.thing, you can either:
Create a copy of thing manually and return it (Java won't do the copying automatically for you!) or,
Make the type of thing immutable
The thing returned by getThing() is a reference to the private variable thing
If you need to modify it, use foo.getThing().doSomeMethod()
What you currently do in changeThing: grab a reference to foos thing and assign it to the method variable thing. Then you assign to the variable thing a completely different thing. This does not change anything inside the instance foo
Yes the original member within foo is mutated if you actually mutate the object. Currently you are simply reassigning the variable you hold which doesn't perform any action on the object itself.
Consider this
public class Foo {
private FooInner thing = new FooInner();
public FooInner getThing() {
return this.thing;
}
public String toString() {
return Integer.toString(thing.i);
}
class FooInner{
int i = 0;
}
public static void main(String[] args) {
Foo foo = new Foo();
System.out.println(foo); //Prints 0
FooInner thing = foo.getThing();
thing.i = 10;
System.out.println(foo); //Prints 10
}
}
At first, you should understand the concept of reference types...
Consider the following code :
Foo f = new Foo();
This is, in fact, two orders
1, new foo() => it creates a foo in part of memory called heap, it is your real var or content
2, Foo f => the above var(content) address put in f. so f is a reference to content.
In your code, when you return this.thing, in fact, you return a reference or address of an object.
and when you write :
foo.getThing() return the thing that is in Foo class and it is a reference or pointer to an object and then
Object thing = foo.getThing();
put the address of Foo's thing in another reference named thing.
And it means that both of them are pointing to the same content...
see comments:
public class Foo {
private Object thing;
//constructor to create an Foo-Object-Instance
public Foo() { ... }
//method to return a characteristic of a Foo-Object,
//whereas this characteristic is an object, not a primitive data type
public Object getThing() {
return this.thing;
}
}
public class Bar {
//constructor to create an Bar-Object-Instance
public Bar() { ... }
//returns an object and does whatever it's supposed to do within the { ... }
//I wonder how's object connected to bar?
public Object makeNewThing() { ... }
public void changeThing() {
//is Foo a subtype of Bar?
//creating a Foo-Class-Instance (object)
//that contains a variable Object (which is not the data as it would be with
//primitive data types, but a reference to the data)
Foo foo = new Foo();
//and with "foo.getThing()" you get the reference ("address")
//of the Object foo's characteristic "thing" (which is an object
//as well, so you copy the address to the data) and add it to the
//new "Object thing", which
//you have declared on the left side of the =
//so you have two object variables pointing/with reference to the same data
Object thing = foo.getThing();
//when you use makeAnewThing - whatever stands in there - to change the
//object ("thing") variables data, then the data of the object will
//be changed if so stated in the { } and
//hence basically the thing-object (or "variable")
//within the foo-object as well,
//because both variable names are pointing to the same data
thing = makeThing();
}
}
There might be a confusion, because you name both "thing", i. e. the object thing declared outside foo-object and the object-variable "thing" within foo-class.
Important is the difference between objects and primitive data types, whereas object variables or names like "String objectname" or "Object foo" contain the reference to the data:
//declare an object named abs, which does not point to data
Object abc;
//declare an object named def and (right side of =) initiate it with data or variable or whatever the constructor says what's to be done
Object def = new Object();
//copy the reference ("address" of def-Object) to abc
abc = def;
//now we have one data thingi with two references to it, i. e. abc and def
If you now add changes to abc, then the changes will, when stated in the method, be added to the data abc is pointed to. If you then use something like def.getData(), the changed data will be returned, as both, abc and def, point to the same data.
Is there a way to automatically add the private qualifier while new variables are declared in Eclipse?
In a way I would like to override the default access to private
I don't know of a way to do this.
However, the way i write code, it would rarely be necessary. That's because i rarely define fields by hand; instead, i let Eclipse create them, and when it does that, it makes them private.
Say i want to create a class Foo with a single field bar of type int. Start with:
public class Foo {
}
Put the cursor in the class body, hit control-space, and choose 'default constructor' from the proposals menu. You now have:
public class Foo {
public Foo() {
// TODO Auto-generated constructor stub
}
}
Delete the helpful comment. Now manually add a constructor parameter for bar:
public class Foo {
public Foo(int bar) {
}
}
Now put the cursor on the declaration of bar and hit control-1. From the proposals menu, choose 'assign parameter to new field':
public class Foo {
private final int bar;
public Foo(int bar) {
this.bar = bar;
}
}
Bingo. You now have a private field.
There is a similar sequence of automatic operations which can create a field from an existing expression in a method (first creating a local variable, then promoting it to a field).
If you consider it more important to you than performance and readability, I suppose you could configure a relatively convenient solution as follows. I wouldn't do this myself.
For class and instance variables, modify the class template in preferences to incorporate this:
private static Object fields = new Object () {
// declare all class variables here
};
private Object vars = new Object () {
// declare all instance variables here
};
For local variables, modify the method template in preferences to incorporate this:
private Object locals = new Object () {
// declare all local variables here
};
Class variable x will be declared in fields. It will be private at this.class.fields.x.
Instance variable y will be declared in vars. It will be private at this.vars.y.
Local variable z will be declared in locals. It will be private at locals.z.
If you do this, you can expect your entire program to be slower and use more memory that it would otherwise.
I have a public class, which needs 7 parameters to be passed down. At the moment, I am able to make 3 of them being passed to constructor and another 4 to a public method in the class . Like this:
Public Class AClass{
private XClass axClass;
private String par4;
private String par5;
private String par6;
private String par7;
public AClass(String par1, String par2, String par3){
aXClass = new XClass(par1,par2,par3);
}
public execute(String par4,String par5, String par6, String par7){
//this is needed because they are used in other private methods in this class
this.par4 = par4;
this.par5 = par5;
this.par6 = par6;
this.par7 = par7;
//call other private methods within this class.
//about 7 lines here
}
}
My question is, is this the right way to ask client of the class to passing in paramters?
There shouldn't be anything stopping you from passing 7 parameters to a constructor, if that's what you want. I don't know if there's a maximum number of parameters that can be passed to a method in Java, but it's certainly higher than 7 if there is a max.
When you create a class and its public methods, you're creating an interface on how to use and access that class. So technically what you've done so far is correct. Is it the "right way" to ask the client of a class to pass in arguments? That's up to you, the designer of the interface.
My first instinct when I saw 7 parameters being passed was to silently ask "Is there some relationship between some or all of these parameters that might mean they'd go together well in a class of their own?" That might be something you address as you look at your code. But that's a question of design, not one of correctness.
I'd go for the Builder Pattern instead of many constructor parameters as suggested by
Effective Java Item 2: Consider a builder when faced with many constructor parameters
Here's a simple class to illustrate:
public class Dummy {
private final String foo;
private final String bar;
private final boolean baz;
private final int phleem;
protected Dummy(final Builder builder) {
this.foo = builder.foo;
this.bar = builder.bar;
this.baz = builder.baz;
this.phleem = builder.phleem;
}
public String getBar() {
return this.bar;
}
public String getFoo() {
return this.foo;
}
public int getPhleem() {
return this.phleem;
}
public boolean isBaz() {
return this.baz;
}
public static class Builder {
private String foo;
private String bar;
private boolean baz;
private int phleem;
public Dummy build() {
return new Dummy(this);
}
public Builder withBar(final String bar) {
this.bar = bar;
return this;
}
public Builder withBaz(final boolean baz) {
this.baz = baz;
return this;
}
public Builder withFoo(final String foo) {
this.foo = foo;
return this;
}
public Builder withPhleem(final int phleem) {
this.phleem = phleem;
return this;
}
}
}
You would instantiate it like this:
Dummy dummy = new Dummy.Builder()
.withFoo("abc")
.withBar("def")
.withBaz(true)
.withPhleem(123)
.build();
The nice part: you get all the benefits of constructor parameters (e.g. immutability if you want it), but you get readable code too.
Can't you just make a class/hashmap that stores these parameters and pass this to the function?
public excute(Storageclass storageClass){
//this is needed because they are used in other private methods in this class
this.par4 = storageClass.getPar4();
this.par5 = storageClass.getPar5();
this.par6 = storageClass.getPar6();
this.par7 = storageClass.getPar7();
//or
this.storageClass = storageClass;
}
I don't really see the problem with that.
In any case you could create a "Request" object or something like this:
class SomeClass {
private String a;
private String b;
....
public SomeClass( Request r ) {
this.a = r.get("a");
this.b = r.get("b");
...
}
public void execute( Request other ) {
this.d = other.get("d");
this.e = other.get("d");
...
}
}
See also: http://c2.com/cgi/wiki?TooManyParameters
Without knowing the use of the child class, I can say that there is nothing inherently wrong with what you have done.
Note though that you have to declare
private XClass axClass;
in the variables of your AClass.
However, you say 'I am able to make....' Does this mean there is some problem with declaring this another way?
I don't care for it much, because an object should be 100% ready to be used after its constructor is called. It's not as written in your example.
If the parameters passed into the execute method can simply be consumed, and that's the method of interest for clients, I see no reason for them to be data members in the class.
Without knowing more about your ultimate aims it's hard to tell. But I would re-think this implementation.
If you're planning on introducing an AClass.someMethod() that needs to know par4-7 without requiring you to have called AClass.excute(), then clearly you should be passing the parameters in the constructor.
On the other hand: if you can construct an instance of this object with only par1-3 and do something meaningful with it besides call excute() then it makes sense to allow the object to be constructed with fewer than the full seven parameters.
Yet my own aesthetic is to try and limit the number of "modes" that an object can be in which make certain methods work and others fail. So ideally, a fully-constructed object is ready to run any method the programmer might call. I'd worry about the design issue more than be too concerned about the sheer number of parameters to the constructor.
But as others have pointed out, sometimes there is a natural grouping of these parameters which can deserve objects of their own. For instance: in many APIs instead of passing (x, y, width, height) all over the place they use rectangle objects.
As others already wrote, it is technically correct to pass 7 parameters, although not very 'user-friendly', if you can say so.
Since you didn't write much about this class, I can suggest one small thing: in constructor you're just creating XClass object, so it would be sane to create this object before and pass it as a single parameter.
Something like this:
...
XClass aXClass = new XClass(par1, par2, par3);
AClass aClass = new AClass(aXClass);
...
And this is the constructor:
public AClass(XClass aXClass) {
this.aXClass = aXClass;
}
I'm working on some classes that get part of their configuration from global variables, e.g.
class MyClass {
public void MyClass(Hashtable<String, String> params) {
this.foo = GlobalClass.GLOBALVAR.get("foo");
this.bar = GlobalClass.GLOBALVAR.get("bar");
this.params = params;
}
}
This is bad for a couple of reasons, GLOBALVAR talks to a database to get some of the variables and this makes it really hard to make unit tests. The other problem is that I have many (dozens) of classes that inherit from MyClass, so I can't easily change the constructor signature.
My current solution is to create an additional default constructor and setter methods for params, foo and bar.
class MyClass {
// Other code still here for backwards compatibility.
public void MyClass() {
// Do nothing much.
}
public void setParams(Hashtable<String, String> params) {
this.params = params;
}
public void setFoo(Foo foo) {
this.foo = foo;
}
public void setBar(Bar bar) {
this.bar = bar;
}
}
Any ideas on a good way to refactor this, besides the way I did it? My other thought would be to use a factory method, but I'm afraid I'll run into polymorphic substitution problems.
I think I would start by doing the following. It let's your existing code work without modification, and allows you to add new constructors to the subclasses as you can. Once all of the subclasses have the new constructor, and all of the calls to the old constructors are gone, you can get rid of the GlobalClass and the constructors that use it. You can also then, hopefully, work on cleaning up the GLOBALVAR (the Car class in my code).
import java.util.Hashtable;
class MyClass
{
private final Foo foo;
private final Bar bar;
private final Hashtable<String, String> params;
public MyClass(final Hashtable<String, String> params)
{
this(params, GlobalClass.GLOBALVAR);
}
// added constructor
public MyClass(final Hashtable<String, String> params,
final FooBar fooBar)
{
this.foo = fooBar.getFoo();
this.bar = fooBar.getBar();
this.params = params;
}
}
class MySubClass
extends MyClass
{
public MySubClass(final Hashtable<String, String> params)
{
super(params);
}
// added constructor
public MySubClass(final Hashtable<String, String> params,
final FooBar fooBar)
{
super(params, fooBar);
}
}
// unchanged
class GlobalClass
{
public static Car GLOBALVAR;
}
// added interface
interface FooBar
{
Foo getFoo();
Bar getBar();
}
class Car
// added implements
implements FooBar
{
private Foo foo = new Foo();
private Bar bar = new Bar();
public Object get(final String name)
{
if(name.equals("foo"))
{
return (foo);
}
if(name.equals("bar"))
{
return (bar);
}
throw new Error();
}
// added method
public Foo getFoo()
{
return ((Foo)get("foo"));
}
// added method
public Bar getBar()
{
return ((Bar)get("bar"));
}
}
// unchanged
class Foo
{
}
// unchanged
class Bar
{
}
I think you should introduce an interface to put a layer of abstraction between the global variable collection and its consumers.
interface GlobalVars {
String get(String key);
}
You should introduce a constructor with limited scope, probably package-private
MyClass(GlobalVars globals, Map<String, String> params) {
// create the object
}
And then provide public static factory methods to use this constructor.
public static MyClass newMyClass(Map<String, String> params) {
return new MyClass(GlobalClass.GLOBAL_VAR, params);
}
With this design you can pass in a mock implementation of GlobalVars in a unit test from within the same package by explicitly invoking the constructor.
Addendum: Since params seems to be a required field, I would definitely make it final and avoid the approach where you add mutators to overwrite them.
private final Map<String, String> params;
Also, make a defensive copy to prevent l33t h4x.
this.params = Collections.unmodifiableMap(params);
Your class should take all of its dependencies in the constructor. It's a good idea to make it impossible to create an invalid or uninitialized instance of classes. Make foo and bar private and final, and set them in the constructor.
A slight variation on your approach would be to have an object of type GLOBALVAR in the class and use that instead of the actual global (that refactoring should be a simple search/replace). You can default the new variable to the actual global variable and provide an override for testing.
This GlobalClass.GLOBALVAR should be chopped up up into logical units. That way it would be easier to make mock objects for the unit tests. For example in my CAD/CAM metal cutting application I have a MaterialList, a SheetSizeList, PartNestingParameters, etc.
I don't have a huge list of variables stuff into one giant AppParameter class. They all hang off a ShopStandards object. For Unit Test involving a specific PartNestingParmeters I will just go ShopStandards.PartNestingParmeters = new MockPartNestingParameterTest114(). The test will run not realizing that the Part Nesting Parameters are a mockup. Plus this save me from having to doing dozens of assignments just to get the ShopStandard setup correctly for the test.
We have even more automated where many of the Mock load from files saved during the test run during initial development.
Since you mention that you have the freedom to modify the class hierarchy.
Change the base MyClass ctor to take in 3 parameters params, foo and bar. Comment out the GlobalVar references and simply cache passed in values
Compile.. this should throw up a bunch of compile errors - no ctor which takes 1 parameter.
Fix each one to pass in GlobalVar.get("foo") and GlobalVar.get("bar"). Get it to build.
Refine: Now minimize hits to the DB by lazy load and caching the foo and bar values. Expose via some property on GlobalVar.