What is a Field in Java ?
1. Introduction
Java is an object-oriented programming language which uses “object” concept to group data and methods in a class. A variable defined in a class is called a field. A field is declared by specifying its type and name.
In this example, I will demonstrate:
- Declare a field for the primitive data type, object, and collection
- Add
static
,final
,transient
, and access modifiers to fields - Access fields via Java reflection
- Inherits fields from the parent class
2. Technologies Used
The example code in this article was built and run using:
- Java 11
- Maven 3.3.9
- Eclipse Oxygen
- Junit 4.12
3. Maven Project
In this step, I will create a Java maven project which has two packages:
jcg.zheng.demo.data
– this package includes four classes:PrimitiveFields
,ObjectFields
,CollectionFields
, andEnumExample
.jcg.zheng.demo.modifier
– this package includes four classes:AccessModifiers
,InstanceModifiers
,RuntimeModifiers
, andChildExample
.
3.1 Dependencies
I will include Junit
in the pom.xml
.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>jcg.zheng.demo</groupId> <artifactId>java-field-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <build> <sourceDirectory>src</sourceDirectory> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <release>11</release> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> </project>
3.1.1 Enum Example
In this step, I will create an EnumExample
which is used in an ObjectFields
class.
EnumExample.java
package jcg.zheng.demo.data; public enum EnumExample { GOLD, SILVER; }
3.2 Field Modifier
Java supports three types of modifiers:
- Access modifiers:
public
,protected
,private
, anddefault
- Run-time modifiers:
transient
andvolatile
- Instance modifiers:
static
andfinal
In this step, I will create three classes to demonstrate how to use these modifiers on fields.
3.2.1 Access Modifier
Java provides four access modifiers:
private
– a field with theprivate
modifier can be accessed only inside the same class.default
– a field without any access modifier can be accessed inside the class itself and in the same package as this class.public
– a field with thepublic
modifier can be accessed from all classes.protected
– a field with theprotected
modifier can be accessed by sub-classes, the same class, and the classes in the same package.
In this step, I will create an AccessModifiers
class which has four fields, one for each access modifier.
AccessModifiers.java
package jcg.zheng.demo.modifier; public class AccessModifiers { private int intField; public Long longField; Integer packageField; protected String stringField; public AccessModifiers(final int privateIntField) { super(); this.intField = privateIntField; } @Override public String toString() { return "FieldAccessExample [packageField=" + packageField + ", intField=" + intField + ", stringField=" + stringField + ", longField=" + longField + "]"; } }
3.2.2 Instance Modifier
Java provides two instance modifiers:
static
– a field with thestatic
modifier can be accessed before any objects of its class are created, and without reference to any object. There is only a single copy of static variable created and shared among all the instances of the class.final
– a field with thefinal
modifier cannot be assigned again. If afinal
variable holds a reference to an object, then the state of the object may be changed by operations on the object, but the variable always refer to the same object.
In this step, I will create an InstanceModifiers
which has four static final
variables and two final
variables.
InstanceModifiers.java
package jcg.zheng.demo.modifier; import jcg.zheng.demo.data.PrimitiveFields; public class InstanceModifiers { public static final String INT_FIELD = "intField"; public static final String LONG_FIELD = "longField"; public static final String PACKAGE_FIELD = "packageField"; public static final String STRING_FIELD = "stringField"; final String field1 = "Fixed Value"; final PrimitiveFields field2 = new PrimitiveFields(); }
3.2.3 Run-time Modifier
Java supports two run-time modifiers:
transient
– a field with thetransient
modifier will not be serialized.volatile
– a field with thevolatile
modifier does not cache value.
In this step, I will create a RuntimeModifiers
which has transient
volatile
variables and two final
variables.
RuntimeModifiers.java
package jcg.zheng.demo.modifier; import java.io.Serializable; public class RuntimeModifiers implements Serializable { private static final long serialVersionUID = 4192336936121085734L; private String name; private transient String password; private static volatile RuntimeModifiers instance; public static RuntimeModifiers getInstance() { if (instance == null) { synchronized (RuntimeModifiers.class) { if (instance == null) { instance = new RuntimeModifiers(); } } } return instance; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "RuntimeModifierExample [name=" + name + ", password=" + password + "]"; } }
3.3 Primitive Data Type
Java supports eight primitive data type: char
, byte
, int
, short
, long
, float
, double
, and boolean
. A primitive data type variable has a default value.
In this step, I will create a PrimitiveFields
class which has eight fields, one for each primitive type.
PrimitiveFields.java
package jcg.zheng.demo.data; public class PrimitiveFields { private boolean booleanField; private byte byteField; private char charField; private double doubleField; private float floatField; private int intField; private long longField; private short shortField; public byte getByteField() { return byteField; } public char getCharField() { return charField; } public double getDoubleField() { return doubleField; } public float getFloatField() { return floatField; } public int getIntField() { return intField; } public long getLongField() { return longField; } public short getShortField() { return shortField; } public boolean isBooleanField() { return booleanField; } public void setBooleanField(boolean booleanField) { this.booleanField = booleanField; } public void setByteField(byte byteField) { this.byteField = byteField; } public void setCharField(char charField) { this.charField = charField; } public void setDoubleField(double doubleField) { this.doubleField = doubleField; } public void setFloatField(float floatField) { this.floatField = floatField; } public void setIntField(int intField) { this.intField = intField; } public void setLongField(long longField) { this.longField = longField; } public void setShortField(short shortField) { this.shortField = shortField; } }
3.4 Object
Java provides java.lang.Object class which is the parent class of all classes.
In this step, I will create an ObjectFields
class which has fields belong to object types. It’s a good practice to initialize an object field to avoid the NullPointerException.
ObjectFields.java
package jcg.zheng.demo.data; public class ObjectFields { private EnumExample enumField; private PrimitiveFields objectField; private String stringField; public EnumExample getEnumField() { return enumField; } public PrimitiveFields getObjectField() { return objectField; } public String getStringField() { return stringField; } public void setEnumField(EnumExample enumField) { this.enumField = enumField; } public void setObjectField(PrimitiveFields objectField) { this.objectField = objectField; } public void setStringField(String stringField) { this.stringField = stringField; } }
3.5 Collection
In this step, I will create a CollectionFields
class which has collection fields. It’s a good practice to initialize the collection object to avoid the NullPointerException.
CollectionFields.java
package jcg.zheng.demo.data; import java.util.ArrayList; import java.util.List; public class CollectionFields<T> { private int[] arrayField; private List<T> listField_initialized = new ArrayList<>(); public void addListField_initialized(T element) { this.listField_initialized.add(element); } public int[] getArrayField() { return arrayField; } public List<T> getListField_initialized() { return listField_initialized; } public void setArrayField(int[] arrayField) { this.arrayField = arrayField; } }
3.6 Inheritance
In this step, I will create a ChildExample
class which extends from AccessModifiers
. The parent’s protected
and public
fields are available to the child class.
ChildExample.java
package jcg.zheng.demo.modifier; public class ChildExample extends AccessModifiers { private String name; public ChildExample(final int privateIntField, final String name) { super(privateIntField); this.name = name; } @Override public String toString() { return "ChildExample [name=" + name + ", packageField=" + packageField + ", stringField=" + stringField + ", longField=" + longField + "]"; } }
4. JUnit Test
4.1 PrimitiveFieldsTest
In this step, I will create a PrimitiveFieldsTest
class to test the primitive data type fields.
PrimitiveFieldsTest.java
package jcg.zheng.demo.data; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; import jcg.zheng.demo.data.PrimitiveFields; /** * Test the default value for the field with primitive type and the getter and setter * @author Mary Zheng * */ public class PrimitiveFieldsTest { private PrimitiveFields testClass = new PrimitiveFields(); @Test public void test_field_boolean() { assertFalse(testClass.isBooleanField()); testClass.setBooleanField(true); assertTrue(testClass.isBooleanField()); } @Test public void test_field_char() { assertEquals('\u0000', testClass.getCharField()); testClass.setCharField('M'); assertEquals('M', testClass.getCharField()); } @Test public void test_field_double() { assertEquals(0.00, testClass.getDoubleField(), 2); testClass.setDoubleField(34.8); assertEquals(34.8, testClass.getDoubleField(), 2); } @Test public void test_field_int() { assertEquals(0, testClass.getIntField()); testClass.setIntField(1); assertEquals(1, testClass.getIntField()); } @Test public void test_field_long() { assertEquals(0, testClass.getLongField()); testClass.setLongField(100l); assertEquals(100l, testClass.getLongField()); } @Test public void test_field_short() { assertEquals(0, testClass.getShortField()); testClass.setShortField((short) 1); assertEquals(1, testClass.getShortField()); } @Test public void test_field_byte() { assertEquals(0, testClass.getByteField()); testClass.setByteField((byte) 1); assertEquals(1, testClass.getByteField()); } @Test public void test_field_float() { assertEquals(0.00, testClass.getFloatField(), 2); testClass.setFloatField(34.8f); assertEquals(34.8, testClass.getFloatField(), 2); } }
Execute mvn test -Dtest=PrimitiveFieldsTest
and capture output here.
Output
------------------------------------------------------- T E S T S ------------------------------------------------------- Running jcg.zheng.demo.data.PrimitiveFieldsTest Tests run: 8, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.13 sec Results : Tests run: 8, Failures: 0, Errors: 0, Skipped: 0
4.2 ObjectFieldsTest
In this step, I will create an ObjectFieldsTest
class to initialize and read the object fields.
ObjectFieldsTest.java
package jcg.zheng.demo.data; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import org.junit.Test; import jcg.zheng.demo.data.EnumExample; import jcg.zheng.demo.data.ObjectFields; import jcg.zheng.demo.data.PrimitiveFields; public class ObjectFieldsTest { private ObjectFields testClass = new ObjectFields(); @Test public void test_field_enum() { assertNull(testClass.getEnumField()); testClass.setEnumField(EnumExample.GOLD); assertEquals(EnumExample.GOLD, testClass.getEnumField()); } @Test public void test_field_object() { assertNull(testClass.getObjectField()); testClass.setObjectField(new PrimitiveFields()); assertEquals(0, testClass.getObjectField().getIntField()); } @Test public void test_field_string() { assertNull(testClass.getStringField()); testClass.setStringField("Mary"); assertEquals("Mary", testClass.getStringField()); } }
Execute mvn test -Dtest=ObjectFieldsTest
and capture output here.
Output
------------------------------------------------------- T E S T S ------------------------------------------------------- Running jcg.zheng.demo.data.ObjectFieldsTest Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.122 sec Results : Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
4.3 CollectionFieldsTest
In this step, I will create a CollectionFieldsTest
class to initialize and add an element to a collection field.
CollectionFieldsTest.java
package jcg.zheng.demo.data; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; public class CollectionFieldsTest { private CollectionFields testClass = new CollectionFields(); @Test public void test_field_intArray() { int[] arrayField = new int[2]; arrayField[0] = 1; arrayField[1] = 4; testClass.setArrayField(arrayField); assertEquals(1, testClass.getArrayField()[0]); assertEquals(4, testClass.getArrayField()[1]); } @Test public void test_field_list() { assertTrue(testClass.getListField_initialized().isEmpty()); testClass.addListField_initialized(5); assertFalse(testClass.getListField_initialized().isEmpty()); assertEquals(5, testClass.getListField_initialized().get(0).intValue()); } }
Execute mvn test -Dtest=CollectionFieldsTest
and capture output here.
Output
------------------------------------------------------- T E S T S ------------------------------------------------------- Running jcg.zheng.demo.data.CollectionFieldsTest Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.119 sec Results : Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
4.4 AccessModifiersTest
In this step, I will create an AccessModifierTest
class that has public
, protected
, private
, and default package
fields.
AccessModifiodersTest.java
package jcg.zheng.demo.modifier; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import org.junit.Test; public class AccessModifiersTest { private AccessModifiers testClass = new AccessModifiers(3); @Test public void child_class_can_access_default_protected_public() { System.out.println(testClass.toString()); assertNull(testClass.packageField); assertNull(testClass.longField); assertNull(testClass.stringField); testClass.packageField = Integer.valueOf(5); testClass.stringField = "Mary"; testClass.longField = Long.valueOf(12); System.out.println(testClass.toString()); assertEquals(5, testClass.packageField.intValue()); assertEquals("Mary", testClass.stringField); assertEquals(12, testClass.longField.intValue()); } }
Execute mvn test -Dtest=AccessModifiersTest
and capture output here.
Output
------------------------------------------------------- T E S T S ------------------------------------------------------- Running jcg.zheng.demo.modifier.AccessModifiersTest FieldAccessExample [packageField=null, intField=3, stringField=null, longField=null] FieldAccessExample [packageField=5, intField=3, stringField=Mary, longField=12] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.234 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
- line 5, 6: The
private
fields can be accessed within the same class.
4.5 ChildExampleTest
In this step, I will create a ChildExampleTest
class which shows the child object inherits the public
and protected
fields from the parent class.
ChildExampleTest.java
package jcg.zheng.demo.modifier; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import org.junit.Test; import jcg.zheng.demo.modifier.ChildExample; public class ChildExampleTest { private ChildExample testClass = new ChildExample(3, "Test"); @Test public void child_class_can_access_default_protected_public() { System.out.println(testClass.toString()); assertNull(testClass.packageField); assertNull(testClass.stringField); assertNull(testClass.longField); testClass.packageField = Integer.valueOf(1); testClass.stringField = "Zheng"; testClass.longField = Long.valueOf(2); System.out.println(testClass.toString()); assertEquals(1, testClass.packageField.intValue()); assertEquals("Zheng", testClass.stringField); assertEquals(2, testClass.longField.intValue()); } }
Execute mvn test -Dtest=ChildExampleTest
and capture output here.
Output
------------------------------------------------------- T E S T S ------------------------------------------------------- Running jcg.zheng.demo.modifier.ChildExampleTest ChildExample [name=Test, packageField=null, stringField=null, longField=null] ChildExample [name=Test, packageField=1, stringField=Zheng, longField=2] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.203 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
4.6 InstanceModifiersTest
In this step, I will create an InstanceModifiersTest
class which shows final
fields are not assignable.
InstanceModifiersTest.java
package jcg.zheng.demo.modifier; import static org.junit.Assert.assertEquals; import org.junit.Test; public class InstanceModifiersTest { private InstanceModifiers testClass = new InstanceModifiers(); @Test public void test_static() { assertEquals("intField", InstanceModifiers.INT_FIELD); assertEquals("longField", InstanceModifiers.LONG_FIELD); assertEquals("packageField", InstanceModifiers.PACKAGE_FIELD); assertEquals("stringField", InstanceModifiers.STRING_FIELD); } @Test public void test_final() { assertEquals("Fixed Value", testClass.field1); // testClass.field2 = new PrimitiveFields(); } }
Execute mvn test -Dtest=InstanceModifiersTest
and capture output here.
Output
------------------------------------------------------- T E S T S ------------------------------------------------------- Running jcg.zheng.demo.modifier.InstanceModifiersTest Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.164 sec Results : Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
- line 23 : can not re-assign the
final
field.
4.7 RuntimeModifersTest
In this step, I will create a Junit test to show the transient
fields are not serialized.
RuntimeModifiersTest.java
package jcg.zheng.demo.modifier; import static org.junit.Assert.assertNull; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import org.junit.Test; public class RuntimeModifiersTest { private static final String SERIALIZED_FILE_NAME = "transient.ser"; private RuntimeModifiers testClass = RuntimeModifiers.getInstance(); @Test public void transient_not_serialized() { serializedObj(); RuntimeModifiers deObj = deserializedObj(); assertNull(deObj.getPassword()); System.out.println(deObj.toString()); } private void serializedObj() { try { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(SERIALIZED_FILE_NAME)); testClass.setName("Mary"); testClass.setPassword("shouldNotSerialized"); oos.writeObject(testClass); oos.close(); System.out.println(testClass.toString()); } catch (IOException e) { e.printStackTrace(); } } private RuntimeModifiers deserializedObj() { RuntimeModifiers ret = null; try { ObjectInputStream ooi = new ObjectInputStream(new FileInputStream(SERIALIZED_FILE_NAME)); ret = (RuntimeModifiers) ooi.readObject(); ooi.close(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } return ret; } }
Execute mvn test -Dtest=RuntimeModifiersTest
and capture output here.
Output
------------------------------------------------------- T E S T S ------------------------------------------------------- Running jcg.zheng.demo.modifier.RuntimeModifiersTest RuntimeModifierExample [name=Mary, password=shouldNotSerialized] RuntimeModifierExample [name=Mary, password=null] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.217 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
- line 5: The original object’s
password
has value - line 6: The
transient password
is not serialized
5. Access Field via Reflection
In this step, I will create a FieldReflectionDemo
to show how to read and write the fields via java.lang.reflect package.
FieldReflectionDemo.java
package jcg.zheng.demo; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import jcg.zheng.demo.data.CollectionFields; import jcg.zheng.demo.data.EnumExample; import jcg.zheng.demo.data.ObjectFields; import jcg.zheng.demo.data.PrimitiveFields; import jcg.zheng.demo.modifier.AccessModifiers; import jcg.zheng.demo.modifier.ChildExample; import jcg.zheng.demo.modifier.InstanceModifiers; import jcg.zheng.demo.modifier.RuntimeModifiers; public class FieldReflectionDemo { public static void main(String[] args) { displayClassFields(EnumExample.GOLD); displayClassFields(new PrimitiveFields()); displayClassFields(new ObjectFields()); displayClassFields(new CollectionFields<Integer>()); displayClassFields(new AccessModifiers(3)); displayClassFields(new ChildExample(3, "Test")); displayClassFields(new InstanceModifiers()); displayClassFields(new RuntimeModifiers()); } private static void displayClassFields(Object obj) { try { Field[] allFields = obj.getClass().getDeclaredFields(); System.out.print("\nClass " + obj.getClass().getName() + " has fields: "); for (Field f : allFields) { boolean updated = false; f.setAccessible(true); System.out.printf("\n\t %s %s = %s ", Modifier.toString(f.getModifiers()), f.getName(), f.get(obj)); if (InstanceModifiers.INT_FIELD.equalsIgnoreCase(f.getName())) { f.set(obj, 47); updated = true; } else if (InstanceModifiers.PACKAGE_FIELD.equalsIgnoreCase(f.getName())) { f.set(obj, Integer.valueOf(2)); updated = true; } else if (InstanceModifiers.STRING_FIELD.equalsIgnoreCase(f.getName())) { f.set(obj, "Java code geek"); updated = true; } else if (InstanceModifiers.LONG_FIELD.equalsIgnoreCase(f.getName())) { f.set(obj, Long.valueOf(1000)); updated = true; } if (updated) { System.out.printf("\n\t *Updated* %s %s = %s ", Modifier.toString(f.getModifiers()), f.getName(), f.get(obj)); } } } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) { e.printStackTrace(); } } }
Execute it as a Java application java jcg.zheng.demo.FieldReflectionDemo
and capture output here.
Output
c:\MaryZheng\Workspaces\jdk12\java-field-demo\target\classes>java jcg.zheng.demo.FieldReflectionDemo Class jcg.zheng.demo.data.EnumExample has fields: public static final GOLD = GOLD public static final SILVER = SILVER private static final $VALUES = [Ljcg.zheng.demo.data.EnumExample;@25618e91 Class jcg.zheng.demo.data.PrimitiveFields has fields: private booleanField = false private byteField = 0 private charField = private doubleField = 0.0 private floatField = 0.0 private intField = 0 *Updated* private intField = 47 private longField = 0 *Updated* private longField = 1000 private shortField = 0 Class jcg.zheng.demo.data.ObjectFields has fields: private enumField = null private objectField = null private stringField = null *Updated* private stringField = Java code geek Class jcg.zheng.demo.data.CollectionFields has fields: private arrayField = null private listField_initialized = [] Class jcg.zheng.demo.modifier.AccessModifiers has fields: private intField = 3 *Updated* private intField = 47 public longField = null *Updated* public longField = 1000 packageField = null *Updated* packageField = 2 protected stringField = null *Updated* protected stringField = Java code geek Class jcg.zheng.demo.modifier.ChildExample has fields: private name = Test Class jcg.zheng.demo.modifier.InstanceModifiers has fields: public static final INT_FIELD = intField public static final LONG_FIELD = longField public static final PACKAGE_FIELD = packageField public static final STRING_FIELD = stringField final field1 = Fixed Value final field2 = jcg.zheng.demo.data.PrimitiveFields@3ab39c39 Class jcg.zheng.demo.modifier.RuntimeModifiers has fields: private static final serialVersionUID = 4192336936121085734 private name = null private transient password = null private static volatile instance = null
- line 14, 16, 22, 28: the
private
fields are updated via reflection - line 30 : the
public
field is updated via reflection - line 34: the
protected
field is updated via reflection
6. Summary
In this example, I explained that a field is a building block of a Java object. It is defined by its type and name. I also demonstrated how to use Java modifiers to manage the availability, instance, and runtime behavior.
7. Download the Source Code
This example consists of a Maven project which demonstrates a Field in Java.
You can download the full source code of this example here: What is a Field in Java
Your article is excellent