#define in Java
Asked Answered
T

9

84

I'm beginning to program in Java and I'm wondering if the equivalent to the C++ #define exists.

A quick search of google says that it doesn't, but could anyone tell me if something similar exists in Java? I'm trying to make my code more readable.

Instead of myArray[0] I want to be able to write myArray[PROTEINS] for example.

Truly answered 18/12, 2009 at 8:58 Comment(3)
In modern C++ you should be using a typed constant rather than a #define for thatSlather
Yes, #define is C-style. In C++ use const instead. See Scott Meyers "Effective C++" book, Item 1.Chuppah
as @PeteKirkham mentioned, using macros in this way is not considered best practice. Macros do have their place, such as logging, getting file and line meta-data, and cross-platform support. However, this use-case has more modern approaches that don't rely on macrosNegrito
F
110

No, because there's no precompiler. However, in your case you could achieve the same thing as follows:

class MyClass
{
    private static final int PROTEINS = 0;

    ...

    MyArray[] foo = new MyArray[PROTEINS];

}

The compiler will notice that PROTEINS can never, ever change and so will inline it, which is more or less what you want.

Note that the access modifier on the constant is unimportant here, so it could be public or protected instead of private, if you wanted to reuse the same constant across multiple classes.

Fetor answered 18/12, 2009 at 9:0 Comment(0)
M
48

Comment space too small, so here is some more information for you on the use of static final. As I said in my comment to the Andrzej's answer, only primitive and String are compiled directly into the code as literals. To demonstrate this, try the following:

You can see this in action by creating three classes (in separate files):

public class DisplayValue {
    private String value;

    public DisplayValue(String value) {
        this.value = value;
    }

    public String toString() {
        return value;
    }
}

public class Constants {
    public static final int INT_VALUE = 0;
    public static final DisplayValue VALUE = new DisplayValue("A");
}

public class Test {
    public static void main(String[] args) {
        System.out.println("Int   = " + Constants.INT_VALUE);
        System.out.println("Value = " + Constants.VALUE);
    }
}

Compile these and run Test, which prints:

Int    = 0
Value  = A

Now, change Constants to have a different value for each and just compile class Constants. When you execute Test again (without recompiling the class file) it still prints the old value for INT_VALUE but not VALUE. For example:

public class Constants {
    public static final int INT_VALUE = 2;
    public static final DisplayValue VALUE = new DisplayValue("X");
}

Run Test without recompiling Test.java:

Int    = 0
Value  = X

Note that any other type used with static final is kept as a reference.

Similar to C/C++ #if/#endif, a constant literal or one defined through static final with primitives, used in a regular Java if condition and evaluates to false will cause the compiler to strip the byte code for the statements within the if block (they will not be generated).

private static final boolean DEBUG = false;

if (DEBUG) {
    ...code here...
}

The code at "...code here..." would not be compiled into the byte code. But if you changed DEBUG to true then it would be.

Murtha answered 18/12, 2009 at 9:44 Comment(2)
Definitely a +1 just for the effort!Countercheck
Just want to add that java doesn't do the same for enums.Dorsett
M
6
static final int PROTEINS = 1
...
myArray[PROTEINS]

You'd normally put "constants" in the class itself. And do note that a compiler is allowed to optimize references to it away, so don't change it unless you recompile all the using classes.

class Foo {
  public static final int SIZE = 5;

  public static int[] arr = new int[SIZE];
}
class Bar {
  int last = arr[Foo.SIZE - 1]; 
}

Edit cycle... SIZE=4. Also compile Bar because you compiler may have just written "4" in the last compilation cycle!

Merodach answered 18/12, 2009 at 9:0 Comment(0)
W
4

Java doesn't have a general purpose define preprocessor directive.

In the case of constants, it is recommended to declare them as static finals, like in

private static final int PROTEINS = 100;

Such declarations would be inlined by the compilers (if the value is a compile-time constant).

Please note also that public static final constant fields are part of the public interface and their values shouldn't change (as the compiler inlines them). If you do change the value, you would need to recompile all the sources that referenced that constant field.

Wilhelm answered 18/12, 2009 at 9:0 Comment(2)
Well, private static finals are not really a part of the public interface. :) For public static finals this is true, though.Sturges
@Mombe, correct. I wrote it initially as public, but then changed without updating the answer.Wilhelm
T
3

There is preprocessor for Java which provides directives like #define, #ifdef, #ifndef and many others, for instance PostgresJDBC team uses it to generate sources for different cases and to not duplicate code.

Traceetracer answered 18/1, 2018 at 20:55 Comment(0)
I
1

Most readable solution is using Static Import. Then you will not need to use AnotherClass.constant.

Write a class with the constant as public static field.

package ConstantPackage;

public class Constant {
    public static int PROTEINS = 1;
}

Then just use Static Import where you need the constant.

import static ConstantPackage.Constant.PROTEINS;

public class StaticImportDemo {

    public static void main(String[]args) {

        int[] myArray = new int[5];
        myArray[PROTEINS] = 0;

    }
}

To know more about Static Import please see this stack overflow question.

Intersidereal answered 2/1, 2018 at 13:38 Comment(0)
W
1

Manifold Preprocessor implemented as a javac compiler plugin is designed exclusively for conditional compilation of Java source code. It uses familiar C/C++ style of directives: #define, #undef, #if, #elif, #else, #endif, #error. and #warning.

It has Maven and Gradle plugins.

Wandering answered 5/7, 2020 at 20:42 Comment(0)
M
0

Simplest Answer is "No Direct method of getting it because there is no pre-compiler" But you can do it by yourself. Use classes and then define variables as final so that it can be assumed as constant throughout the program
Don't forget to use final and variable as public or protected not private otherwise you won't be able to access it from outside that class

Mortician answered 30/5, 2017 at 11:25 Comment(0)
S
0

Java Primitive Specializations Generator supports /* with */, /* define */ and /* if */ ... /* elif */ ... /* endif */ blocks which allow to do some kind of macro generation in Java code, similar to java-comment-preprocessor mentioned in this answer.

JPSG has Maven and Gradle plugins.

Scrubby answered 8/4, 2019 at 18:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.