2

I have a class with a method that generates random data to fill arrays with. The class had the data member private final Random rnd that is initialized in the constructor with new Random();. This is used in the method for generating data for arrays.

For example

package test;

import java.util.Random;

public class WorkWithArrays {

    WorkWithArrays(Object[] arr) {
        rand = new Random();
        fillArrays(arr);
    }

    /*fills arrays with random data;
      since this method is called from constructor
      must be declared final*/
    public final void fillArrays(Object[] arr) {
        //code goes here
    }

    /*some other methods and data members*/

     final private Random rand;
}

I am writing a new class which I also need to fill arrays with random values. Is there a way I could not have to rewrite the same method? I could extend the class or I could make the method static. Since I only need fillArrays() making it static seems like the better option over extending.

So let's make it static.

public static final void fillArrays(Object[] arr) {
   //code goes here
}

Now fillArrays() uses rand which is a problem because rand isn't static. So why not make it static? Now in WorkWithArrays we no longer initialize rand in the constructor but have it final static private Random rand = new Random(); as a data member. Is this right? It seems like bad practice to initialize things outside of the constructor.

Now I can do

package test;

MyNewClass {
    someMethod() {
        int[] x = new int[25];
        WorkWithArrays.fillArrays(x);
    }
}
Celeritas
  • 14,489
  • 36
  • 113
  • 194
  • What's wrong with declaring it inside the method? – christopher Aug 08 '14 at 23:24
  • I recommend reviewing what `final` means, as it is not legal on a `static` method. :) – Qix - MONICA WAS MISTREATED Aug 08 '14 at 23:25
  • @Qix yes I thought of that, so I don't need `final` now that the method is `static` right? In what sense is it not legal, it does compile? – Celeritas Aug 08 '14 at 23:27
  • Before we get too far ahead of ourselves: You have two classes, both of which need to fill arrays with random values. But arrays of what? Are the arrays in the two classes the same type of array, or different? Are they arrays of a number type, or arrays of some other class, and if the latter, what's the definition of a "random value" of that class--how do you generate it? – ajb Aug 08 '14 at 23:34
  • @Celeritas It will compile, but static analyzers will warn that it's invalid/pointless. `final` on methods indicates the method cannot be overridden; however, static members cannot be overridden to begin with. See my answer for more information on that. – Qix - MONICA WAS MISTREATED Aug 08 '14 at 23:35

3 Answers3

2

It is not bad practice; as Warren pointed out there is a static initializer construct that is used for just this.

For instance, to make a class with utility-like methods ('functions' that don't really require state), there are a couple of things you can do.

Make the class itself final

This prevents extensions of the class, which wouldn't make sense.

public final class WorkWithArrays {
  // ...
}

Make the constructor private

This prevents the class from being initialized

private WorkWithArrays() {}

Create a static randomizer

You could create/initialize it by itself (which isn't bad practice at all!)

private static final Random rand = new Random();

or with the aforementioned static initializer

private static Random rand;
static {
  rand = new Random();
}

Note that final can only be used with static properties if it is initialized in-line.

Make your random array fill method static

As easy as

public static void fillArrays(Object[] arr) {
  // code goes here
}

This is one way of achieving a design pattern known as a singleton class, and is actually very common throughout OOP languages.

In Java, instead of creating a getInstance()-type method, instances are commonly stored locally (or no instance is created at all, such as is the case here) and the static methods refer to the internally stored instance.

Initialization logic goes in the static { } initializer block, which is executed when the Java classloader first loads the class.

Note that, in your example (at the time of writing), you had the final keyword on a static method. This is not necessary, and is often caught by static analyzers as invalid/pointless.


I'm not one to usually write out code for the OP, but the following is a perfectly fine approach to structure your class1.

public final class WorkWithArrays {
  private static final Random RAND; // = new Random();
  static {
    WorkWithArrays.RAND = new Random();
  }

  private WorkWithArrays() {}

  public static void fillArrays(Object[] array) {
    for (int i = 0, len = array.length; i < len; i++) {
      array[i] = WorkWithArrays.RAND.nextInt();
    }
  }
}

1Imports have been omitted

Community
  • 1
  • 1
Qix - MONICA WAS MISTREATED
  • 14,451
  • 16
  • 82
  • 145
  • 1
    +1. This is the "classic" OO way of doing it. A modern, enterprisey system would instead use dependency injection. – that other guy Aug 08 '14 at 23:44
  • @Qix Singleton is a Java pattern, but that doesn't mean it's a good one. People use singleton when they want unscoped global values, you know, just like C global variables! Also the static initialization block is not mean to help "instantiate" the `Class` class, it is meant to assure the __initialization order__ in edge cases where multiple static variables are entangled such that only a certain initialization order ensures correct state. – Edwin Buck Aug 08 '14 at 23:53
  • `Singleton is a Java pattern` wrong, it is not specific to Java. `People use singleton when they want unscoped global values, you know, just like C global variables` Wrong again. Unscoped C global variables are just that - *unscoped*. They are dangling symbols with no ownership, thus making them *wild-west*-ey and thus hard to maintain/predict. Singleton classes provide a scope, and **do** provide logic and proper ownership and management. What you believe `static {}` to be meant for is your own concern - it was simply provided here for informational accuracy. – Qix - MONICA WAS MISTREATED Aug 08 '14 at 23:56
  • @Qix Exactly what is the scope of a Singleton? If you can tell me where a singleton stops being reachable, I would be appreciative. There are a lot of people who consider them harmful http://stackoverflow.com/a/138012/302139 How do you address their concerns? And what I believe `static { }` is meant to be is not due to my opinion, it is laid out in the Java language specification, and was designed to solve a classic problem of early C++ initialization. – Edwin Buck Aug 09 '14 at 00:44
  • @EdwinBuck That link is referring to singletons that *contain a static state*. The OP's singleton class is doing no such thing other than a `Random` object, which is hardly state. You also failed to read the followup comments on that - one of which by [Johannes Rudolph](http://jorudolph.wordpress.com/2009/11/22/singleton-considerations/). – Qix - MONICA WAS MISTREATED Aug 09 '14 at 00:48
  • @Qix Random contains state. If it didn't, it wouldn't take a seed. It generates a pseudo-random number, meaning that it appears to be random, but actually follows a pattern. The seed determines where on the cyclic path you start at. And I read the follow up. The first few points were in complete agreement, but sidelined the concerns. One point of amusement "singletons are not going to be implemented in any other way" was laughably wrong, as they were not thread safe in the original implementation, and are now properly implemented with enums. I'll take my pointers from pros, thank you. – Edwin Buck Aug 09 '14 at 01:09
  • Have fun living in the 90's. Programming has evolved out of bell labs if you haven't noticed; there are practical uses of statics. Deal with it. – Qix - MONICA WAS MISTREATED Aug 09 '14 at 01:11
0

Static variables are often initialized outside the constructor. In fact, in Java, there's the concept of a "static initializer", which is specifically designed to initialize static variables outside of any constructor, if the initialization is too complex for a simple assignment.

Warren Dew
  • 8,790
  • 3
  • 30
  • 44
0

The more you use static, the further you drift away from object orientation. Static is not subject to polymorphisim, and rarely does using a state promote data hiding (as all the instances tend to cross-communicate when going through static variables).

In addition, many (not all) details of arrays are at odds with object oriented programming too, as arrays are holders of data without the possibility of combining code and data. As a result, arrays lack behavior and delegate the responsibility of data correctness to other non-related pieces of code.

For an object oriented solution:

public class RandomIntList {
   private int[] values;

   public RandomIntList(int size) {
      values = new int[size];
      Random random = new Random();
      for (int i = 0; i < size; i++) {
        values[i] = random.nextInt();
      }
   }

}

Note that now you can cleanly identify which objects are RandomIntLists and which are not, which is not really possible with int[]s.

Of course, if you add something like

public int[] asArray() {
   return values;
}

You let the cat out of the bag, because other code could modify the internal state of the class without going through the class's boundary (aka interface or methods). So to keep your classes object oriented, you sometimes need to copy (when the data can be mutated).

public int[] asArray() {
    return Arrays.copyOf(values, values.size);
}
Edwin Buck
  • 69,361
  • 7
  • 100
  • 138
  • `The more you use static, the further you drift away from object orientation.` -1, this is a complete blanket statement. You're now introducing ownership conflicts, resulting in copied arrays and **redundant data**, which could cause more problems than it solves. The OP is perfectly fine looking for a static solution, assuming proper ownership of the array is handled. – Qix - MONICA WAS MISTREATED Aug 08 '14 at 23:52
  • @Qix I didn't just make a blanket statement, I backed it up with rationale. Something that you seem to have completely disregarded. Exactly how does one do polymorphisim with static? How about inheritance. Java wasn't meant to be OO at the expense of ever being useful to the masses of C and C++ programmers. Like all languages, it stood firm on some points and compromised on others. You can do everything in Java without requiring static (except in those instances where the underlying libraries require it) you just need more diligence with your references and object construction. – Edwin Buck Aug 08 '14 at 23:56
  • `You can do everything in Java without requiring static` if that's the case, then why does the JRE provide classes with static methods almost everywhere you look? Again, a blanket statement backed up by an **opinion** - not rationale. – Qix - MONICA WAS MISTREATED Aug 08 '14 at 23:58
  • You can do everything in Java without requiring static, it's not an opinion, it's a fact. Just make one instance of your Factory, instead of defining static factory methods. That's not an opinion, but stating that it is the better / best way to do it is an opinion. Also, I couldn't help but notice that you didn't even acknowledge any questions about OOP I presented with respect to the static issue. Do you only have attacks, or can you answer them? – Edwin Buck Aug 09 '14 at 00:05
  • I addressed your entire answer - the fact you wrap an array and then clone it for accessing is absolutely absurd and unnecessary for the OP's use case. I'm not going to argue with you, as it is not appropriate here in the comments. I disagree with your "fact" that everything can be done without statics. If that was the case, the JRE wouldn't use statics and statics wouldn't be a part of the language spec. Simple as that. – Qix - MONICA WAS MISTREATED Aug 09 '14 at 00:08
  • @Qix, ok, so you "addressed (my) entire answer". Exactly where is the answer to "Exactly how does one do polymorphisim with static? How about inheritance?" Seems that you are skipping over a lot of points, and being a bit dismissive about it. After all, nearly nothing is "Simple as that". And everything can be done without statics. You don't need static to be turning complete. However, doing everything with static is proving the old adage that "Some people can write FORTRAN in any language" – Edwin Buck Aug 09 '14 at 00:20
  • Because anyone who knows basic OOP constructs knows that *you can't*. I thought that was inferred. The OP doesn't want to - there is no point, the method doesn't need any state. Also, turing* - and if you're really going to pull out ol' Alan, then there is really no winning this argument now, is there? ;) – Qix - MONICA WAS MISTREATED Aug 09 '14 at 00:22
  • Thanks for the downvote revenge, by the way. :) That -6 *really* hurt. – Qix - MONICA WAS MISTREATED Aug 09 '14 at 00:28
  • @Qix And since you can't apply some of the most foundational OOP principles to static items, it would seem that an overabundance of static would lead to less OOP. And what downvote? You downvoted me, but I haven't downvoted anyone in days. Please take a moment and chill. I've been pretty polite considering how your treatment is coming across over here. If you really think I'm abusing you, go over to meta stack overflow and ask for moderation. Otherwise, just drop it. Life is too short. – Edwin Buck Aug 09 '14 at 00:36