I'm aware that you could call a method from a constructor, but it could lead to problems later on if the method could be overridden. The following code is just an example I've written demonstrating my issue:
Let say I have the following subclass:
private boolean isActive;
public ChargeGun(String gameObjectID, String gameObjectName, String desc, int numberofshots, int damage, boolean isActive) {
super(gameObjectID, gameObjectName, desc, numberofshots, damage);
setAttributes(isActive);
}
public ChargeGun(String gameObjectID, String gameObjectName, int numberofshots, int damage, boolean isActive) {
super(gameObjectID, gameObjectName, numberofshots, damage);
setAttributes(isActive);
}
private final void setAttributes(boolean isActive)
{
this.isActive = isActive;
}
The boolean isActive is specific to ChargeGun and not any other gun. Given that I have two constructors in my subclass, rather than type isActive = true twice, could I call a private final method to do it? The reason is, if my attributes for ChargeGun grow, then I would have to add attributes in both constructors. If I do it with a private final method, everything is set in one place. Is this bad practice?
I can't chain the ChargeGun constructors because both call the super classes constructor.
A private method cannot be overriden, you do not also need to mark it final (which also means it cannot be overriden). Just one of final or private would be sufficient. However, the method needs to be modified slightly. Like,
private void setAttributes(boolean isActive)
{
this.isActive = isActive;
}
your version always sets it to true. If that is intentional I would remove the setter entirely, and do something like
private final boolean isActive = true;
which is a declaration and initialization of an immutable field.
If you need your setAttributes, it certainly means you have common variables to always set the same way in multiple constructors. Wouldn't it be more clear to have a "full constructor" which have all the assignment you make in setAttributes, and other shorter versions of your version calling the full version ?
Also, you really should consider using Builder pattern which clearly deals with those object that can be constructed in many different ways. If you thing it is a lot of work, just know that some plugins for IDE such as InnerBuilder make it easy to generate. If you look at how languages evolve, you will see more and more builder-like api (Stream, Optional...).
Related
For everyone who is talking about the fact that the object is in an "unitialized state", please refer to the answer to this question which shows that an object reference can be passed around, dereferenced, have methods invoked from it, and have fields accessed before a constructor terminates and all fields have been assigned (including final fields).
So here's the use case:
public class Entity {
private final String name;
public Entity() {
this(toString()); //Nope, Chuck Testa
}
public Entity(String name) {
this.name = name;
}
}
The compiler error is:
Cannot refer to an instance method while explicitly invoking a constructor.
Note that toString() has not been overriden and is the default call from Object.
I'm certainly interested in the philosophical/technical reasons behind this, so if anyone can explain that, that would be an awesome bonus. But I'm looking for a way to call toString() from that default constructor as it refers down to the more specific one with more arguments. The actual use case is a bit more complicated and ends up referring all the way down to a constructor with four arguments, but that shouldn't really matter.
I know I could do something like this...
private static final String TO_STRING_CONSTRUCTOR_ARGUMENT = "aflhsdlkfjlkswf";
public Entity() {
this(TO_STRING_CONSTRUCTOR_ARGUMENT);
}
public Entity(String name) {
this.name = name == TO_STRING_CONSTRUCTOR_ARGUMENT ? toString() : name;
}
... but it seems like a pretty inelegant solution.
So, any way to pull it off? Or any recommended best practices to deal with this situation?
I would prefer not to pass this around until the object is created. Instead I would do this:
public class Entity {
private final String name;
public Entity() {
this(null); // or whatever
}
public Entity(String name) {
this.name = name;
}
public String getName() {
return name != null ? name : Objects.hashCode(this);
}
}
If you can live without the final name, you can use an initializer block:
public class Entity {
private String name;
{name = this.toString();}
public Entity() {
}
public Entity(String name) {
this.name = name;
}
}
this is only available after all calls to this() or super() are done. The initializer runs first after the constructors call to super() and is allowed to access this.
As for the reasons why that is a compiler error, please see section 8.8.7 of the JLS. The reasons why this was made a compiler error are not clear, but consider that the constructor chain has to be the first thing executed when new'ing an Object and look at the order of evaluation here:
public Entity() {
this(toString());
}
toString() is evaluated first before the even the super constructor is invoked. In general this leaves open all kinds of possibilities for uninitialized state.
As a personal preference, I would suggest that everything an object needs to have in order to create valid state should be available within its constructor. If you have no way of providing valid state in a default constructor without invoking other methods defined in the object hierarchy, then get rid of the default constructor and put the onus on the users of your class to supply a valid String to your other constructor.
If you are ultimately just trying invoke the other constructor with the value of toString(), then I would suggest the following instead:
public Entity() {
name = toString();
}
which accomplishes the same goal you set out to achieve and properly initializes name.
As explained in the JLS this is not allowed before the instance is initialized.
However, there are ways to handle your scenario in a consistent manner.
As I see your case, you want to signify either a generated value (toString()) or a user provided value, which can be null.
Given this constraints, using TO_STRING_CONSTRUCTOR_ARGUMENT is failing for at least one specific use case, however obscure it may be.
Essentially you will need to replace the String with an Optional similar to what exists in Google Guava and will be included in Java 8, and seen in many other languages.
Having a StringOptional/StringHolder or whatever you choose, similar to this:
public class StringOptional {
private String value;
private boolean set = false;
public StringOptional() {}
public StringOptional(String value) {
this.value = value;
this.set = true;
}
public boolean isSet() { return set; }
public String getValue() { return value; }
}
Then you can call constructors with the knowledge of the inferred path.
public class Entity {
public Entity() {
this(New StringOptional());
}
public Entity(String s) {
this(new StringOptional(s));
}
private Entity(StringOptional optional) {
super(optional);
}
}
And store this for subsquent need:
if (optional.isSet() ? optional.getValue() : toString();
This is how I usually would handle a maybe-null scenario, hope it augments as an answer.
You cannot 'use' an instance that has not been created yet. By calling a second constructor you are postponing the creation, you cannot use it before the call or in the action of calling.
You can use a static method factory in your class Entity, and put the constructor private:
public class Entity {
private String name;
private Entity() {
}
public Entity(String name) {
this.name = name;
}
public static Entity createEntity() {
Entity result = new Entity();
result.name = result.toString();
return result;
}
}
Eg.
boolean isCurrent = false;
What do you name its getter and setter?
Suppose you have
boolean active;
Accessors method would be
public boolean isActive(){return this.active;}
public void setActive(boolean active){this.active = active;}
See Also
Java Programming/Java Beans
Code Conventions for the Java Programming Language
http://geosoft.no/development/javastyle.html#Specific
is prefix should be used for boolean variables and methods.
isSet, isVisible, isFinished, isFound, isOpen
This is the naming convention for
boolean methods and variables used by
Sun for the Java core packages. Using the is prefix solves a common
problem of choosing bad boolean names
like status or flag. isStatus or
isFlag simply doesn't fit, and the
programmer is forced to chose more
meaningful names.
Setter methods for boolean variables
must have set prefix as in:
void setFound(boolean isFound);
There are a few alternatives to the is
prefix that fits better in some
situations. These are has, can and
should prefixes:
boolean hasLicense();
boolean canEvaluate();
boolean shouldAbort = false;
For a field named isCurrent, the correct getter / setter naming is setCurrent() / isCurrent() (at least that's what Eclipse thinks), which is highly confusing and can be traced back to the main problem:
Your field should not be called isCurrent in the first place. Is is a verb and verbs are inappropriate to represent an Object's state. Use an adjective instead, and suddenly your getter / setter names will make more sense:
private boolean current;
public boolean isCurrent(){
return current;
}
public void setCurrent(final boolean current){
this.current = current;
}
I believe it would be:
void setCurrent(boolean current)
boolean isCurrent()
Maybe it is time to start revising this answer? Personally I would vote for setActive() and unsetActive() (alternatives can be setUnActive(), notActive(), disable(), etc. depending on context) since "setActive" implies you activate it at all times, which you don't. It's kind of counter intuitive to say "setActive" but actually remove the active state.
Another problem is, you can can not listen to specifically a SetActive event in a CQRS way, you would need to listen to a 'setActiveEvent' and determine inside that listener wether is was actually set active or not. Or of course determine which event to call when calling setActive() but that then goes against the Separation of Concerns principle.
A good read on this is the FlagArgument article by Martin Fowler: http://martinfowler.com/bliki/FlagArgument.html
However, I come from a PHP background and see this trend being adopted more and more. Not sure how much this lives with Java development.
There is a markable point between setter/getter method of the data type Boolean and boolean in side a class ( for pojo/entity).
For both Boolean and boolean the setter method should be setXXX() but getter method would be getXXX() and isXXX() respectively
Example:
(a) if property is defines as Boolean
private Boolean active;
the setter/getter method
public Boolean getCheck() { // getXXX()
return check;
}
public void setCheck(Boolean check) {
this.check = check;
}
(b) if property is defines as boolean
private boolean check;
the setter/getter method
public boolean isCheck() { // isXXX()
return check;
}
public void setCheck(boolean check) {
this.check = check;
}
It should just be get{varname} like every other getter. Changing it to "is" doesn't stop bad variable names, it just makes another unnecessary rule.
Consider program generated code, or reflection derivations.
It's a non-useful convention that should be dropped at the first available opportunity.
It is highly recommended to use an adjective to name a boolean field. If you generate getter and setter using IntelliJ, you will find out that the getter is isCurrent() for both of boolean fields current and isCurrent.
We can take a look at IntelliJ community source code, its test data shows that no matter whether your boolean field name starts with is or not, the name of getter starts with is.
class Getter {
boolean foo;
boolean isBar;
boolean hasBaz;
#java.lang.SuppressWarnings("all")
public boolean isFoo() {
return this.foo;
}
#java.lang.SuppressWarnings("all")
public boolean isBar() {
return this.isBar;
}
#java.lang.SuppressWarnings("all")
public boolean isHasBaz() {
return this.hasBaz;
}
}
It will be very confusing when you want to call the getter, when you boolean field name starts with is. Besides, when your colleagues want to get the value of a boolean field you defined, they will only know the getter' s name instead of the field' s name. In that case, the prefix is is not necessary.
Here is another example, when I retrieve data from database to instantiate a object of Employee, the value of isRetired is always false. Because Java does not find an appropriate setter, the value of a boolean field is always default value, say false, which is not expected.
class Employee{
private int age;
private boolean isRetired;
...
public boolean setRetired(boolean isRetired){
this.isRetired = isRetired;
}
}
private boolean current;
public void setCurrent(boolean current){
this.current=current;
}
public boolean hasCurrent(){
return this.current;
}
Setter: public void setCurrent(boolean val)
Getter: public boolean getCurrent()
For booleans you can also use
public boolean isCurrent()
As a setter, how about:
// setter
public void beCurrent(boolean X) {
this.isCurrent = X;
}
or
// setter
public void makeCurrent(boolean X) {
this.isCurrent = X;
}
I'm not sure if these naming make sense to native English speakers.
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;
}
(For those who read my previous question, this is the same teacher and the same project.)
My teacher 'inspected' my code for a web application project and provided some suggestions. One of the suggestions was to use the this keyword even in this situation:
private String getUsername() {
return username;
}
So if I follow his advice, that would become:
private String getUsername() {
return this.username;
}
I asked him why and he told me that there is another usage for the this keyword other than for clearing up ambiguities. A quick googling returned no results for another usage of the this keyword. Even the Java tutorial from Sun mentioned no other usages that would fit in this situation.
this also allows you access to the surrounding class instance and its members from within a nested class, e.g.
public class OuterClass
{
private class InnerClass
{
public OuterClass getOuter()
{
return OuterClass.this;
}
}
}
You use it to chain constructors as well:
public class Foo
{
private final String name;
public Foo()
{
this("Fred");
}
public Foo(string name)
{
this.name = name;
}
}
(For chaining to a superclass constructor, use super(...).)
Additionally, there are some weird times where you can use it from an inner class to specify exactly which member you're after. I don't remember the exact syntax, fortunately - I don't need to use it often.
An very important one that hasn't been mentionned, is the use of this for method chaining used in fluent APIs. In this design pattern, all methods return this, regardless of what they do, allowing you to so stuff like:
dog.setColor("black").setSize("tall").makeDangerous().bark();
using an API constructed, so:
public Dog setColor(String c) {
color=c;
return this;
}
Some people think it is good practice to always use the keyword this for class fields. This can be useful in the following situation:
class MyClass {
private int x = 0;
public void DoSomething(int x) {
int privateFieldValue = this.x; // use field of our class
}
}
Also, you can return this to chain method calls - e.g. in Builder pattern.
class CustomerBuilder
{
private String firstName = "Default";
private String lastName = "Default";
public CustomerBuilder setFirstName(String firstName)
{
this.firstName = firstName;
return this;
}
public CustomerBuilder setLastName(String lastName)
{
this. lastName = lastName;
return this;
}
public Customer build()
{
/* ... do some actions to build a Customer object ... */
}
}
Then, you can use this builder like this:
Customer customer = new CustomerBuilder().setFirstName("John").setLastName("Smith").build();
Always accessing member variables using this. is a coding convention in some places. The idea is probably that it's similar to naming conventions ("All field names must start with an underscore _") but without the ugly name-mangling. (Other places have exactly the opposite convention: avoiding this. unless absolutely necessary).
Personally I don't see any real reason to do it, since all tools you use to access your code should be able to color/style-code each variable/field to make the distinction.
Your grand-dads text-editor is not able to show the difference between accessing a local variable and a field. But that's not a good reason for hard-coding it redundantly in your code.
There is no other usage of the 'this' except for calling another constructor of the same class.
Qualifying access to member variables - even if not needed - is considered best-practice by some developers (I don't). The main point is that it is possible to change the semantics of an assignment without changing that line:
class Foo {
String foo;
void foo() {
// a lot of code
foo = "something"
}
}
May be changed by simply doing the following:
void foo() {
String foo;
// a lot of code
foo = "something"
}
So it's mostly about maintenance and readability - for the price of verbosity.
Using the this keyword will also trigger a warning from the compiler if someone comes along and decides to change the username member to a static variable on you. If you don't use this, the compiler will just play along like everything is cool. And username changing to be static could very well be a bug. So you probably want the warning. And if it isn't a bug, you should change the code that uses username to treat it as if it is static to avoid future bugs / misunderstandings in the code. That way, if someone comes along and changes it back you'll get a new warning.
So, if nothing else, in the context of a getter, it can also trigger compiler warnings when other things change on you. And that is a Good Thing.
public class StateQueryFilter extends FieldQueryFilter {
// private static final Log LOG = LogFactory.getLog(RecommendedParser.class.getName());
public StateQueryFilter() {
super("state", 5f);
super("city", 5f);
super("notdirectory", 5f);
//LOG.info("Added a state query");
}
}
And it reports:
Constructor call must be the first statement in a constructor
Is there a way to make it work?
You can only call super once in a constructor, and it must be the first line.
It does not even make sense to call it more than once as you are doing. Calling super does not create a new object; it just lets the superclass initialize its fields. Are you really trying to initialize the same fields more than once? You probably are trying to create three separate objects, but that is not the way to do it.
See also Using the keyword super in the Java tutorials.
Nope. You are trying to construct the object 3 times, the logic is flawed.
From section 8.8.7 of the Java Language Specification:
The first statement of a constructor
body may be an explicit invocation of
another constructor of the same class
or of the direct superclass
(ยง8.8.7.1).
Note "first" statement - you can't have more than one.
I find constructors which call setter ugly.
Another option is to have a constructor which takes the arguments.
public StateQueryFilter() {
super(/*state*/ 5, /* city */ 5, /*notdirectory*/ 5);
//LOG.info("Added a state query");
}
However it looks like you should be doing something like
public class StateQueryFilter extends FieldQueryFilter {
private final String city;
private final String state;
private final boolean noDirectory;
public StateQueryFilter(String city, String state, boolean noDirectory) {
this.state = state;
this.city = city;
this.notDirectory = notDirectory;
}
}
// later
FieldQueryFilter filter = new StateQueryFiler("Los Angeles", "California", true);
BTW: Don't use float values, they are almost never the best option.