2

I'd like to create a class with about 60 fields of type double inside. Then I need to create different instances of this class, valuing through the constructor only some of these fields (about 4-5 fields), leaving the others as default (0).

The problem is that I don't want to have a 60 parameters constructor, since it would be a waste of time to fill all the required fields. Furthermore, I don't want to create public methods to set fields value one by one.

I was thinking about java Annotation, somenthing like

public @interface MyAnnotation{

    public double f1() default 0;
    public double f2() default 0;
    public double f3() default 0;
    ...
    public double f60() default 0;

}

so that I can then specify only the parameters I need

@MyAnnotation(f1=2.1 , f48=3.5)

Anyway, I don't have much experience on that and I'm not sure it can cope with my needs. Broadly speaking, my object would be to have something like:

MyClass c1 = new MyClass(f1=2.1 , f48=3.5);
MyClass c2 = new MyClass(f4=5 , f30=12.9);

public class MyClass{
    double f1;
    double f2;
    double f3;
    ...
    double f60;
}

Is there a way to get somenthing similar also with class constructors?

P.S. I'm not a programmer but I'm quite aware of Java reflections, so no problem if they would be required.

1
  • 2
    Why don't you explain what you're trying to accomplish with this class? This sounds like a modeling problem. Commented Feb 18, 2016 at 18:04

6 Answers 6

1

Something like this? or am I way off?

    public class Blank{
      public void Blank(int [] fSpots, double[] vaules0{
            }

then loop through setting the specific spots equal to the values?

Sign up to request clarification or add additional context in comments.

2 Comments

This could work for sure, but it implies that I should remember the position (index) of each field, and with 60 fields this could be a bit tricky.
No no, the 'fspots[]' array is used to dictate which indexes need to be different, the values array dictates what the double will be....
1

Look into 'builder' solution. You create a mutable class mirroring your main class, with setters for each field (possibly with fluent api for easier access) and then have your main immutable class take builder as argument and copy data out of it. To avoid manual creation of huge builders, you can use some helpers, like https://projectlombok.org/features/Builder.html

Alternatively, you can use groovy with http://docs.groovy-lang.org/latest/html/documentation/#_named_argument_constructor scala with http://docs.scala-lang.org/tutorials/tour/named-parameters.html or xtend with one of active annotations.

3 Comments

I believe that both scala or groovy can suit my needs. But, how can I use them in an Eclipse based software that works with Java? It is enough to add some libraries to switch from a sintax to the other?
xtend-contrib has a nice implementation as well, see @Buildable: github.com/oehme/xtend-contrib
You would need to install proper plugin for eclipse to get it compiling (together with refactoring/autocompletion and all other IDE goodness) and then add libraries for runtime anyway. For plugins, you can use github.com/groovy/groovy-eclipse/wiki for groovy or scala-ide.org/download/current.html for scala. If you want less invasive dialect, I would suggest xtend from eclipse.org/xtend with annotation mentioned by snorbi above
1

This is crazy, but:

enum Field {

  F1, F2, F3, F48;

  Arg set(Double value)
  {
    return new Arg(this, value);
  }

  static final class Arg
  {
    final Field field;

    final Double value;

    private Arg(Field f, Double v)
    {
      this.field = f;
      this.value = v;
    }
  }

}

final class BadModel
{

  private static final Double ZERO = (double) 0;

  private final Map<Field, Double> fields = new EnumMap<>(Field.class);

  BadModel(Field.Arg... args)
  {
    for (Field.Arg e : args)
      this.fields.put(e.field, e.value);
  }

  Double get(Field field)
  {
    return fields.getOrDefault(field, ZERO);
  }

  public static void main(String... argv)
  {
    BadModel obj = new BadModel(Field.F1.set(2.1), Field.F48.set(Math.PI));
    double f3 = obj.get(Field.F3);
    System.out.println(f3);
  }

}

I encourage you to take a step back and get some help with your underlying problem, before assuming that an object with sparse fields is the answer.

Comments

0

One approach is to implement different constructors, each containing just a few of the fields that should be filled. This is a valuable approach if there are only a few sensible combinations of values that you want to use.

Furthermore, it would be possible to use a Map that stores the values, interpreting all non-stored values as zero. This map could be given to the constructor as argument.

Generally, one should think about the design if one encounters such a large "data class". Maybe it should be split into several classes for different purposes, maybe different data structures like arrays, maps or sets are suitable.

2 Comments

I cannot implement different constructors since there are thousand of possible combinations of fields to be valued. Anyway, the idea of arrays could work, thank you for that. I was thinking about java Annotation just because it allows to specify in the brakets only the fields you're interested in, calling directly the parameter and assigning a value to it. But I really cannot figure out how to adapt it to my scope (having different instances with different values).
I would definitely also consider Maps for storage. Then you do not have to assign all values.
0

I believe a fluent interface can help you. Remember that the default value for double in Java is already 0.0.

public class MyClass {

double f1;
double f2;

public MyClass() {
}

public MyClass f1(double f1) {
    this.f1 = f1;
    return this;
}

public MyClass f2(double f2) {
    this.f2 = f2;
    return this;
}

}



public class Test {

MyClass myClass1 = (new MyClass()).f1(1);
MyClass myClass2 = (new MyClass()).f2(2);
MyClass myClass3 = (new MyClass()).f1(1).f2(2);

}

Comments

0

I haven't found exactly what I was looking for. Anyway, I post the solution I chose just in case someone is interested.

I created a Class with different Fields inside:

public class MyClass{
    double f1;
    double f2;
    ...
    double fn;
}

Then I created an Enum which embeds a getFieldName() method that returns a String equals to MyClass field name:

public enum MyEnum{
    F1("f1"),
    F2("f2"),
    ...
    FN("fn");

    private String name;

    private MyEnum(String fieldName){
        name = fieldName;
    }

    public String getFieldName(){
        return name;
    }
}

Then I created a constructor for MyClass that, taking advantage of java reflections, set values to the specified fields.

public class MyClass{
    double f1;
    double f2;
    ...
    double fn;

    public MyClass(MyEnum[] fieldsName, double[] values){
        for(int i=0; i<fieldsName.lenght; i++){
            try{
                Field f = this.getClass().getDeclaredField(fieldsName[i].getFieldName());
                f.set(this,values[i])
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.