-1

I just started learning Java. IntelliJ is giving me a warning "Static member accessed via instance reference" on line 4. Is it bad, should I fix it, somehow, or should I just ignore it?

Here is my code:

public class MainClass {
    public static void main(String[] args) {
        Dog randomDog = new Dog();
        Dog myDog = new Dog(4, "Charlie", new Dog().breed.Labrador);
        System.out.println("Random dog's name is: " + randomDog.name + ", it's age is: " + randomDog.age + " and it's breed is: " + randomDog.breed);
        System.out.println("My dog's name is: " + myDog.name + ", it's age is: " + myDog.age + " and it's breed is: " + myDog.breed);
    }
}

and the Dog class:

public class Dog {
    int age;
    String name;
    enum breed { Poodle, Shepherd, Labrador }
    breed breed;

    Dog(int age, String name, breed breed) {
        this.age = age;
        this.name = name;
        this.breed = breed;
    }
    Dog() {
        this.age = 0;
        this.name = "Rex";
        this.breed = breed.Labrador;
    }
}
Matīss
  • 3
  • 1
  • 5
    Fix the problem: `Dog.breed.Labrador`. btw, don't call a field the same as a type, it's just confusing. Call the enum `Breed` and the field `breed`. And enum values are, by convention, capitalized. – Andy Turner May 28 '21 at 16:55
  • @AndyTurner It is actually required to rename the enum, because `Dog.breed.Labrador` fails. It looks like the property shadows the enum in that class. – Tom May 28 '21 at 16:59
  • 2
    Q: Is it bad? A: It's just a "warning" - everything will still work as expected. A bigger problem is the naming conflict between "enum breed" and instance variable "breed". You should consider setting explicit visibility (i.e. "public", "private" or "protected") for ALL members. – paulsm4 May 28 '21 at 17:02
  • @paulsm4 "everything will still work as expected" that strongly depends on what you expect, of course. – Andy Turner May 28 '21 at 17:03
  • 1
    @Tom interesting, I wonder how you could refer to `breed` from outside the class without renaming it. Maybe it's another of those funny cases that Java can't handle, like https://stackoverflow.com/questions/50633759/how-to-refer-to-a-class-when-both-simple-and-fully-qualified-names-clash. I guess it depends on context, because `Dog.breed breed = null;` would work, because there it can only be a type. – Andy Turner May 28 '21 at 17:06
  • 1
    @AndyTurner I guess there is no way to do it without fixing the ambiguity. I also found a question with the same issue: [Java Enums and Fields with same name](//stackoverflow.com/q/39917386) – Tom May 28 '21 at 17:18

1 Answers1

2

One issue (which causes others) is that you're hiding the type breed by also having a field of the same name in the same scope.

That's a very rare problem to have, because the naming conventions of Java usually prevent this kind of clash: Types (classes, interfaces, enums, annotations) are usually written in CamelCase whereas field names start with a lower case letter (fieldName). While this is not technically a "rule" that the compiler enforces, following this makes your code much more readable to others and also avoids the follow-up problem of hiding the type. Also note that constant fields.

I also made two changes that are good ideas but not really related to your issue:

  • constant values (i.e. most static final fields an enum constants) use ALL_UPPER casing, so I also changed your Breed values
  • I've moved the nested type definition to the top of your Dog class so as not to hide it within all the instance fields. This is just to keep those things that logically belong together close to each other.
public class Dog {
    enum Breed { POODLE, SHEPHERD, LABRADOR }

    int age;
    String name;
    Breed breed;

    Dog(int age, String name, Breed breed) {
        this.age = age;
        this.name = name;
        this.breed = breed;
    }
    Dog() {
        this.age = 0;
        this.name = "Rex";
        this.breed = Breed.LABRADOR;
    }
}

Changing all these names in the main class and replacing the unneded new Dow().breed with just Dog.Breed produces this working code:

public class MainClass {
    public static void main(String[] args) {
        Dog randomDog = new Dog();
        Dog myDog = new Dog(4, "Charlie", Dog.Breed.LABRADOR);
        System.out.println("Random dog's name is: " + randomDog.name + ", it's age is: " + randomDog.age + " and it's breed is: " + randomDog.breed);
        System.out.println("My dog's name is: " + myDog.name + ", it's age is: " + myDog.age + " and it's breed is: " + myDog.breed);
    }
}
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614