0

I'm new to Java and cannot really understand how to use private static final String[] in other classes.

I have this String[] that I want to access in another class.

private static final String[] NAMES = new String[] {...}
  1. I tried to add @Getter to it, but it still doesn't pass the check with an error: Public static ....getNAME() may expose internal representation by returning ClassName.NAMES
  2. I tried creating a public clone, but I read that it's not a very good approach.

If I want to use a @Getter, how should I do it?

Or if I want to expose a public String[] what would be the right way to do?

Stacy
  • 43
  • 7
  • why would you want to use a private member in other classes ? It is just not the point of private members – midugh Aug 22 '22 at 14:24
  • 2
    `private` would make it so that only methods/fields within the class you defined it in can access it. Note that an array is mutable in that the members of the array can be modified, it shouldn't really be `public` either. There's package-private (no visibility modifier) and `protected`. – Rogue Aug 22 '22 at 14:24
  • 2
    [Controlling Access to Members of a Class](https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html) – fantaghirocco Aug 22 '22 at 14:25
  • I also cannot make String[] public, I get an error saying that `it's a mutable array` – Stacy Aug 22 '22 at 14:25
  • Does this answer your question? [How to read the value of a private field from a different class in Java?](https://stackoverflow.com/questions/1196192/how-to-read-the-value-of-a-private-field-from-a-different-class-in-java) – LinFelix Aug 22 '22 at 14:25
  • @Rogue this is helpful, but how should I structure my code to use a mutable array? – Stacy Aug 22 '22 at 14:26
  • @Stacy it depends on what you're attempting to achieve with `NAME`. Should it be a constant (and ideally unmodifiable)? Or is it describing some type of data for the class it is defined in? I would also ensure you're not naming your class as `Class`, since that is an already-existing name within the JDK. – Rogue Aug 22 '22 at 14:31
  • @Rogue Naming is just an example :) It's immutable constant that has some data. For simplicity, I have multiple Names `public static final String NAME1 = "name1"` and I want to get them all in the `String [] ` – Stacy Aug 22 '22 at 14:33
  • 1
    @Stacy if you truly want something which is immutable, then you will not be able to use a primitive array. You can use a `List` or `Set`, and pair it with `Collections#unmodifiableList` (or likewise for `Set`), if you _truly_ need to expose the constant. Most of the time, you can keep the constant as `private` or `protected`, and simply expose the functionality you'd desire that would use the constant (e.g. `public boolean isName(String someName) { /* check NAME */ }`. Exposing a `public String[]` would typically be a copy-array, not the actual underlying data. – Rogue Aug 22 '22 at 14:35
  • 1
    Or you could create a getter that returns a copy of the array, not with an annotation. – RealSkeptic Aug 22 '22 at 14:36
  • 1
    "*I tried creating a public clone, but I read that it's not a very good approach*" could you add more info here? In case of mutable objects it is *preferred* to have getter which returns copy (possibly even deep copy) if we don't want to allow others to modify original object. Could it be that you read about problems with `clone()` method? If yes then indeed, it was not best design for classes, but calling it on array of immutable type like String is actually acceptable practice. – Pshemo Aug 22 '22 at 14:36

2 Answers2

2

I agree with RealSkeptic's suggestion that you can have getter that can return copy :

private static final String[] NAME = new String[] { "Test","Test1" };

public String[] getName() { 
    return Arrays.copyOf(ClassName.NAME, ClassName.NAME.length);
}

And then, in another class, you can use this method to access elements of array. Here ClassName is name of class you have used for declaring this array.

Rogue
  • 11,105
  • 5
  • 45
  • 71
Ashish Patil
  • 4,428
  • 1
  • 15
  • 36
  • That method should be `static`. And there is no need for Arrays.copyOf. Just `return NAME.clone();` is sufficient. – VGR Aug 22 '22 at 19:48
1

The String[] you receive in the main method is a special case; it is populated with the arguments entered on the command line when starting java. Typically this data is processed immediately and influences how the program runs. If you want to access this array in other classes, you have options:

  • create an instance of the other class, and pass the array as an argument:

    public static void main(String[] args) {
      OtherClass other = new OtherClass(args);
    
  • create an instance of the main class, set the array as a field and add a getter:

    public class MyApp {
    
      private String[] args;
    
      public static void main(String[] args) {
          MyApp myApp = new MyApp();
          myApp.setArgs(args);
          OtherClass other = new OtherClass(myApp);
      }
    
      public String[] getArgs() { return args;}
      public void setArgs(String[]) { this.args = args;}
    ...
    
    public class OtherClass {
    
       public OtherClass(MyApp myApp) {
           String[] args = myApp.getArgs();
    

It all boils down to the same thing: You have to pass or receive the reference via a constructor or method call.

EDIT: If you are worried about the contents of the array being changed, you could for example create a List<String> with the contents of the array. Lists are more flexible to use than arrays, so that's usually what you want anyway:

  public static void main(String[] args) {
    OtherClass other = new OtherClass(new ArrayList<>(Arrays.asList(args)););

...

public class OtherClass {

    private final List<String> data;

    public OtherClass(List<String> data) {
         this.data = data;
    }
Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60