Copyright © 2017 Oracle America, Inc. Legal Notice.
This document proposes changes to the Java Language Specification to support enhancements to the enum
language feature. See JEP 301 for an overview.
An enum declaration specifies a new enum class, a special kind of class type.
In this and other sections, it's preferable to use the term enum class rather than enum type, especially now that there is no longer a one-to-one relationship between enum declarations and actual enum types (i.e., class types, possibly parameterized or raw, that name an enum). That said, there are a few places where JLS uses "enum type" as shorthand for "enum type declaration", in parallel with "class type", "interface type", and "annotation type" (see, e.g., 6.1 and 7.5.1). We don't necessarily propose changing all of those sections.
EnumDeclaration:
{ ClassModifier }
enum
Identifier [ TypeParameters ][ Superinterfaces ] EnumBody
It is a compile-time error if an enum declaration has the modifier abstract
or final
.
An enum declaration is implicitly final
unless it contains at least one enum constant that has a class body (8.9.1).
A nested enum class is implicitly static
. It is permitted for the declaration of a nested enum class to redundantly specify the static
modifier.
This implies that it is impossible to declare an enum class in the body of an inner class (8.1.3), because an inner class cannot have
static
members except for constant variables.
It is a compile-time error if the same keyword appears more than once as a modifier for an enum declaration.
An enum class may be generic (8.1.2) and may declare superinterfaces (8.1.5).
The direct superclass of a non-generic enum class E is Enum
<E>; the direct superclass of a generic enum class E<P1,...,Pn> is Enum
<E<P1,...,Pn>> (8.1.4).
This rule adds a compatibility risk for developers who add type parameters to existing enums—their refactored enum will not work with client code that wants to operate on Enum<E>
. However, most clients don't interact with enums through their Enum
superclass type; when the type is used, it's usually with a wildcard.
An enum class has no instances other than those defined by its enum constants. It is a compile-time error to attempt to explicitly instantiate an enum class (15.9.1).
In addition to the compile-time error, three further mechanisms ensure that no instances of an enum class exist beyond those defined by its enum constants:
- The final
clone
method inEnum
ensures that enum constants can never be cloned.- Reflective instantiation of enum classes is prohibited.
- Special treatment by the serialization mechanism ensures that duplicate instances are never created as a result of deserialization.
The body of an enum declaration may contain enum constants. An enum constant defines an instance of the enum class.
EnumBody:
{
[ EnumConstantList ] [,
] [ EnumBodyDeclarations ]}
EnumConstantList:
EnumConstant {
,
EnumConstant }
EnumConstant:
{ EnumConstantModifier } Identifier [ TypeArguments ]
[
(
[ ArgumentList ])
] [ ClassBody ]
EnumConstantModifier:
Annotation
The following productions from 4.5.1 and 15.12 are shown here for convenience:
TypeArguments:
<
TypeArgumentList>
TypeArgumentList:
TypeArgument {
,
TypeArgument }ArgumentList:
Expression {
,
Expression }
The rules for annotation modifiers on an enum constant declaration are specified in 9.7.4 and 9.7.5.
The Identifier in an EnumConstant may be used in a name to refer to the enum constant.
The scope and shadowing of an enum constant is specified in 6.3 and 6.4.
If an enum class is generic, each enum constant must provide type arguments immediately after the Identifier, or a compile-time error occurs.
We could relax this restriction to allow raw enum constants (that is, enum constants that are instances of the raw enum type rather than a parameterization). But there is no need for such flexibility from a maintenance perspective, since the enum and its constants are declared in the same source file.
It is a compile-time error if any type argument provided by an enum constant is a wildcard (4.5.1).
Where an enum constant of an enum class E provides type arguments T1, ..., Tn, it is a compile time error if the type E<T1,...,Tn> is not well-formed (4.5).
An enum constant may be followed by arguments, which are passed to the constructor of the enum when the constant is created during class initialization as described later in this section. The constructor to be invoked is chosen using the normal rules of overload resolution (15.12.2). If the arguments are omitted, an empty argument list is assumed.
The optional class body of an enum constant implicitly defines an anonymous class declaration (15.9.5) that extends the immediately enclosing enum class, parameterized by the given type arguments, if any. The class body is governed by the usual rules of anonymous classes; in particular it cannot contain any constructors. Instance methods declared in these class bodies may be invoked outside the enclosing enum type only if they override accessible methods in the enclosing enum type (8.4.8).
The anonymous class type implicitly defined by an enum constant of an enum class E is referred to as an enum constant type of E.
Compilation of anonymous classes representing enum constant types requires special treatment, because they can be accessed from separately-compiled code. Per 13.1, the class name is standardized. It is also necessary to set the class accessibility such that any client who can reference the enum constant can also access the class.
It is a compile-time error for the class body of an enum constant to declare an abstract
method.
Suggest deleting this sentence because it's redundant: "the class body is governed by the usual rules of anonymous classes".
It is a compile-time error for an enum constant with a class body to declare a finalizer (12.6). An instance of an enum class may never be finalized.
It is a compile-time error to reference a static
field of an enum class from an instance initializer or instance variable initializer expression of an enum constant's class body, unless the field is a constant variable (4.12.4).
This is a bug fix. These two rules are asserted for enum class bodies (8.9.2), but were not asserted for enum constant bodies. javac
already enforces them.
The arguments and class body of an enum constant appear in a static context (8.1.3). As a result, references to the type parameters and members of the enum class, and uses of the this
and super
keywords, are restricted (6.5.6.1, 8.1.2, 15.8.3, 15.12.3).
Because there is only one instance of each enum constant, it is permitted to use the
==
operator in place of theequals
method when comparing two object references if it is known that at least one of them refers to an enum constant.The equals method in
Enum
is afinal
method that merely invokessuper.equals
on its argument and returns the result, thus performing an identity comparison.
The first paragraph in the above note is presented as normative in JLS 8, but it's not. In particular, "permitted" is not meant to suggest any sort of error condition.
In addition to enum constants, the body of an enum declaration may contain constructor and member declarations as well as instance and static initializers.
EnumBodyDeclarations:
;
{ ClassBodyDeclaration }
The following productions from 8.1.6 are shown here for convenience:
ClassBodyDeclaration:
ClassMemberDeclaration
InstanceInitializer
StaticInitializer
ConstructorDeclarationClassMemberDeclaration:
FieldDeclaration
MethodDeclaration
ClassDeclaration
InterfaceDeclaration
;
Any constructor or member declarations in the body of an enum declaration apply to the enum class exactly as if they had been present in the body of a normal class declaration, unless explicitly stated otherwise.
It is a compile-time error if a constructor declaration in an enum declaration is public
or protected
(6.6).
It is a compile-time error if a constructor declaration in an enum declaration contains a superclass constructor invocation statement (8.8.7.1).
It is a compile-time error to reference a static
field of an enum class from constructors, instance initializers, or instance variable initializer expressions of the enum class, unless the field is a constant variable (4.12.4).
In an enum declaration, a constructor declaration with no access modifiers is private
.
In an enum declaration with no constructor declarations, a default constructor is implicitly declared. The default constructor is private
, has no formal parameters, and has no throws
clause.
In practice, a compiler is likely to mirror the
Enum
class by declaringString
andint
parameters in the default constructor of an enum class. However, these parameters are not specified as "implicitly declared" because different compilers do not need to agree on the form of the default constructor. Only the compiler of an enum class knows how to instantiate the enum constants; other compilers can simply rely on the implicitly declaredpublic
static
fields of the enum class (8.9.3) without regard for how those fields were initialized.
It is a compile-time error if an enum declaration E has an abstract
method m as a member, unless E has at least one enum constant and all of E's enum constants have class bodies that provide concrete implementations of m.
It is a compile-time error for an enum declaration to declare a finalizer (12.6). An instance of an enum class may never be finalized.
...
The members of an enum class E are all of the following:
Members declared in the body of the declaration of E.
Members inherited from Enum
For each enum constant c declared in the body of the declaration of E, E has an implicitly declared public
static
final
field of type E that has the same name as c. The field has a variable initializer consisting of c, and is annotated by the same annotations as c.
If c is declared with a class body, the type of the field is the enum constant type (that is, the anonymous class type of the implicitly-defined anonymous class declaration). Otherwise, the type of the field is the enum class type, parameterized by any provided type arguments.
These fields are implicitly declared in the same order as the corresponding enum constants, before any static
fields explicitly declared in the body of the declaration of E.
An enum constant is said to be created when the corresponding implicitly declared field is initialized.
The following implicitly declared methods:
/** * Returns an array containing the constants of this enum * **class**, in the order they're declared. This method may be * used to iterate over the constants as follows: * * for(E c : E.values()) * System.out.println(c); * * @return an array containing the constants of this enum * **class**, in the order they're declared */ public static E[] values(); /** * Returns the enum constant of this **class** with the specified * name. * The string must match exactly an identifier used to declare * an enum constant in this **class**. (Extraneous whitespace * characters are not permitted.) * * @return the enum constant with the specified name * @throws IllegalArgumentException if this enum **class** has no * constant with the specified name */ public static E valueOf(String name);
It follows that the declaration of enum class E cannot contain fields that conflict with the implicitly declared fields corresponding to E's enum constants, nor contain methods that conflict with implicitly declared methods or override
final
methods of class Enum.
...
...
The scope of an enum constant C declared in an enum class E is the body of E, and any case
label of a switch
statement whose expression is of enum type T, such that T is E, a parameterization of E, or an enum constant type of E (14.11).
...
...
It is a compile-time error to refer to a type parameter of a generic class C in any of the following:
static
member of C (8.3.1.1, 8.4.3.2, 8.5.1).static
member of any type declaration nested within C....
...
A statement or expression occurs in a static context if and only if the innermost method, constructor, instance initializer, static initializer, field initializer, enum constant, or explicit constructor invocation statement enclosing the statement or expression is a static method, a static initializer, the variable initializer of a static variable, an enum constant, or an explicit constructor invocation statement (8.8.7.1).
This is a bug fix: it was not obvious in JLS 8 that references to, say, instance methods, are illegal as arguments to enum constants.
...
Programs must be compiled either into the class
file format specified by The Java Virtual Machine Specification, Java SE 8 Edition, or into a representation that can be mapped into that format by a class loader written in the Java programming language. The resulting class file must have certain properties. A number of these properties are specifically chosen to support source code transformations that preserve binary compatibility. The required properties are:
The class or interface must be named by its binary name, which must meet the following constraints:
The binary name of a top level type (7.6) is its canonical name (6.7).
The binary name of a member type (8.5, 9.5) consists of the binary name of its immediately enclosing type, followed by $
, followed by the simple name of the member.
The binary name of a local class (14.3) consists of the binary name of its immediately enclosing type, followed by $
, followed by a non-empty sequence of digits, followed by the simple name of the local class.
The binary name of an anonymous class that represents an enum constant type (8.9.1) consists of the binary name of the enum class to which it belongs, followed by $$
, followed by the name of the enum constant.
For binary compatibility, anonymous enum constant classes need a standardized name. We use two $
symbols to avoid name clashes, should an enum declare a member class with the same name as one of its enum constants.
The binary name of any other anonymous class (15.9.5) consists of the binary name of its immediately enclosing type, followed by $
, followed by a non-empty sequence of digits.
The binary name of a type variable declared by a generic class or interface (8.1.2, 9.1.2) is the binary name of its immediately enclosing type, followed by $
, followed by the simple name of the type variable.
The binary name of a type variable declared by a generic method (8.4.4) is the binary name of the type declaring the method, followed by $
, followed by the descriptor of the method (JVMS 4.3.3), followed by $
, followed by the simple name of the type variable.
The binary name of a type variable declared by a generic constructor (8.8.4) is the binary name of the type declaring the constructor, followed by $
, followed by the descriptor of the constructor (JVMS 4.3.3), followed by $
, followed by the simple name of the type variable.
...
Given a legal expression denoting a field access in a class C, referencing a field named f that is not a constant variable and is declared in a (possibly distinct) class or interface D, we define the qualifying type of the field reference as follows:
...
The reference to f must be compiled into a symbolic reference to the erasure (4.6) of the qualifying type of the reference, plus the simple name of the field, f. The reference must also include a symbolic reference to the erasure of the declared type of the field binary field type so that the verifier can check that the type is as expected:
If the field is implicitly declared to represent an enum constant (8.9.3), the binary field type is the declaring enum class.
Otherwise, the binary field type is the erasure of the declared type of the field.
Adding a class body to an enum constant (or recompiling an enum with a new source version) shouldn't break binary compatibility. To support this, the compiled type of an enum constant field is always the enum class, not an anonymous enum constant class.
The term binary field type abstractly describes the JVM field descriptor (JVMS 4.3.2). We introduce the term here as a way to describe the mapping from a field's Java type to its JVM descriptor, now that this mapping must be special-cased for enum constants.
While we're at it, we might as well use binary method type, below, to abstractly describe the JVM method descriptor (JVMS 4.3.3).
Given a method invocation expression or a method reference expression in a class or interface C, referencing a method named m declared (or implicitly declared (9.2)) in a (possibly distinct) class or interface D, we define the qualifying type of the method invocation as follows:
...
A reference to a method must be resolved at compile time to a symbolic reference to the erasure (4.6) of the qualifying type of the invocation, plus the erasure of the signature (8.4.2) of the method. The signature of a method must include the simple name of the method, m, and the binary method type, which consists of all of the following as determined by 15.12.3:
void
and does not return a valueA reference to a method must also include either a symbolic reference to the erasure of the return type of the denoted method or an indication that the denoted method is declared void
and does not return a value.
...
A binary representation for a class or interface must also contain all of the following:
...
A specification of each field declared in the class or interface, given as the simple name of the field and a symbolic reference to the erasure of the type of the field binary field type, as described above.
If it is a class, then the erased signature of each constructor, as described above.
For each method declared in the class or interface (excluding, for an interface, its implicitly declared methods (9.2)), its erased signature and return type, as described above simple name and binary method type, as described above.
...
The following formal parameters are declared implicitly in source code:
- The first formal parameter of a constructor of a non-
private
inner member class (8.8.1, 8.8.9).- The first formal parameter of an anonymous constructor of an anonymous class whose superclass is inner or local (not in a static context) (15.9.5.1).
- The formal parameter
name
of thevalueOf
method which is implicitly declared in an enum class (8.9.3).For reference, the following constructs are declared implicitly in source code, but are not marked as mandated because only formal parameters can be so marked in a
class
file (JVMS 4.7.22):
...
Adding or reordering constants in an enum will not break compatibility with pre-existing binaries.
Adding a class body to an enum constant declaration will not break compatibility with pre-existing binaries.
If a pre-existing binary attempts to access an enum constant that no longer exists, the client will fail at run time with a NoSuchFieldError
. Therefore such a change is not recommended for widely distributed enums.
Similarly, removing a class body from an enum constant deletes an implicitly-defined class that might be referenced from other compilation units, leading to linkage errors.
In all other respects, the binary compatibility rules for enums are identical to those for classes.
...
The type of the Expression must be char
, byte
, short
, int
, Character
, Byte
, Short
, Integer
, String
, or an enum class type (8.9), or a subtype of one of these, or a compile-time error occurs.
The switch type of a switch statement is defined as follows:
If Expression has a primitive type, the switch type is the type of Expression.
If the type of Expression is a subtype of Character
, the switch type is char
.
If the type of Expression is a subtype of Byte
, the switch type is byte
.
If the type of Expression is a subtype of Short
, the switch type is short
.
If the type of Expression is a subtype of Integer
, the switch type is int
.
If the type of Expression is a subtype of String
, the switch type is String
.
If Expression has an enum class type or an enum constant type of enum class E, the switch type is either E, if E is non-generic, or E<?,...,?>, if E is generic.
...
Given a switch
statement, all of the following must be true or a compile-time error occurs:
Every case constant associated with the switch statement must be assignment compatible with the type of the switch type (5.2).switch
statement's Expression
If the type of the switch statement's Expression switch type is an enum class type, then every case constant associated with the switch
statement must be an enum constant of that type the named enum class.
No two of the case
constants associated with the switch
statement have the same value.
No case constant associated with the switch
statement is null
.
At most one default
label is associated with the switch
statement.
...
The changes here address an outstanding bug (JDK-6404665): the type of Expression may be a type variable (or intersection?) bounded by a supported class type, rather than the class type itself. JEP 301 exacerbates this situation:
The goal is to allow any case constants that are instances of the appropriate class or enum.
Alternatively, we could agressively prohibit case constants that belong to the appropriate class, but that the type system can prove are incompatible with the Expression (assuming no heap pollution). But this would be a source-incompatible change, and the analysis would be complex.
If the class instance creation expression ends in a class body, then the class being instantiated is an anonymous class. Then:
If the class instance creation expression is unqualified:
The ClassOrInterfaceTypeToInstantiate must denote a class that is accessible, non-final
, and not an enum class; or denote an interface that is accessible. Otherwise a compile-time error occurs.
...
If the class instance creation expression is qualified:
The ClassOrInterfaceTypeToInstantiate must unambiguously denote an inner class that is accessible, non-final
, not an enum class, and a member of the compile-time type of the Primary expression or the ExpressionName. Otherwise, a compile-time error occurs.
...
If a class instance creation expression does not declare an anonymous class, then:
If the class instance creation expression is unqualified:
The ClassOrInterfaceTypeToInstantiate must denote a class that is accessible, non-abstract
, and not an enum class. Otherwise, a compile-time error occurs.
...
If the class instance creation expression is qualified:
The ClassOrInterfaceTypeToInstantiate must unambiguously denote an inner class that is accessible, non-abstract
, not an enum class, and a member of the compile-time type of the Primary expression or the ExpressionName.
...
...
If a method reference expression has the form ClassType ::
[ TypeArguments ] new
, then:
abstract
, and not an enum class, or a compile-time error occurs....
Copyright © 2017 Oracle America, Inc. 4150 Network Circle, Santa Clara, California 95054, U.S.A. All rights reserved.
The Specification is protected by copyright and the information described therein may be protected by one or more U.S. patents, foreign patents, or pending applications. Except as provided under the following license, no part of the Specification may be reproduced in any form by any means without the prior written authorization of Oracle America, Inc. ("Oracle") and its licensors, if any. Any use of the Specification and the information described therein will be governed by the terms and conditions of this Agreement.
Subject to the terms and conditions of this license, including your compliance with Paragraphs 1 and 2 below, Oracle hereby grants you a fully-paid, non-exclusive, non-transferable, limited license (without the right to sublicense) under Oracle's intellectual property rights to:
Review the Specification for the purposes of evaluation. This includes: (i) developing implementations of the Specification for your internal, non-commercial use; (ii) discussing the Specification with any third party; and (iii) excerpting brief portions of the Specification in oral or written communications which discuss the Specification provided that such excerpts do not in the aggregate constitute a significant portion of the Technology.
Distribute implementations of the Specification to third parties for their testing and evaluation use, provided that any such implementation:
does not modify, subset, superset or otherwise extend the Licensor Name Space, or include any public or protected packages, classes, Java interfaces, fields or methods within the Licensor Name Space other than those required/authorized by the Specification or Specifications being implemented;
is clearly and prominently marked with the word "UNTESTED" or "EARLY ACCESS" or "INCOMPATIBLE" or "UNSTABLE" or "BETA" in any list of available builds and in proximity to every link initiating its download, where the list or link is under Licensee's control; and
includes the following notice: "This is an implementation of an early-draft specification developed under the Java Community Process (JCP) and is made available for testing and evaluation purposes only. The code is not compatible with any specification of the JCP."
The grant set forth above concerning your distribution of implementations of the specification is contingent upon your agreement to terminate development and distribution of your "early draft" implementation as soon as feasible following final completion of the specification. If you fail to do so, the foregoing grant shall be considered null and void.
No provision of this Agreement shall be understood to restrict your ability to make and distribute to third parties applications written to the Specification.
Other than this limited license, you acquire no right, title or interest in or to the Specification or any other Oracle intellectual property, and the Specification may only be used in accordance with the license terms set forth herein. This license will expire on the earlier of: (a) two (2) years from the date of Release listed above; (b) the date on which the final version of the Specification is publicly released; or (c) the date on which the Java Specification Request (JSR) to which the Specification corresponds is withdrawn. In addition, this license will terminate immediately without notice from Oracle if you fail to comply with any provision of this license. Upon termination, you must cease use of or destroy the Specification.
"Licensor Name Space" means the public class or interface declarations whose names begin with "java", "javax", "com.oracle" or their equivalents in any subsequent naming convention adopted by Oracle through the Java Community Process, or any recognized successors or replacements thereof.
No right, title, or interest in or to any trademarks, service marks, or trade names of Oracle or Oracle's licensors is granted hereunder. Oracle, the Oracle logo, Java are trademarks or registered trademarks of Oracle USA, Inc. in the U.S. and other countries.
THE SPECIFICATION IS PROVIDED "AS IS" AND IS EXPERIMENTAL AND MAY CONTAIN DEFECTS OR DEFICIENCIES WHICH CANNOT OR WILL NOT BE CORRECTED BY ORACLE. ORACLE MAKES NO REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT THAT THE CONTENTS OF THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE OR THAT ANY PRACTICE OR IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADE SECRETS OR OTHER RIGHTS. This document does not represent any commitment to release or implement any portion of the Specification in any product.
THE SPECIFICATION COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION THEREIN; THESE CHANGES WILL BE INCORPORATED INTO NEW VERSIONS OF THE SPECIFICATION, IF ANY. ORACLE MAY MAKE IMPROVEMENTS AND/OR CHANGES TO THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED IN THE SPECIFICATION AT ANY TIME. Any use of such changes in the Specification will be governed by the then-current license for the applicable version of the Specification.
TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL ORACLE OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES, INCLUDING WITHOUT LIMITATION, LOST REVENUE, PROFITS OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO ANY FURNISHING, PRACTICING, MODIFYING OR ANY USE OF THE SPECIFICATION, EVEN IF ORACLE AND/OR ITS LICENSORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
You will hold Oracle (and its licensors) harmless from any claims based on your use of the Specification for any purposes other than the limited right of evaluation as described above, and from any claims that later versions or releases of any Specification furnished to you are incompatible with the Specification provided to you under this license.
If this Software is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in the Software and accompanying documentation shall be only as set forth in this license; this is in accordance with 48 C.F.R. 227.7201 through 227.7202-4 (for Department of Defense (DoD) acquisitions) and with 48 C.F.R. 2.101 and 12.212 (for non-DoD acquisitions).
You may wish to report any ambiguities, inconsistencies or inaccuracies you may find in connection with your evaluation of the Specification ("Feedback"). To the extent that you provide Oracle with any Feedback, you hereby: (i) agree that such Feedback is provided on a non-proprietary and non-confidential basis, and (ii) grant Oracle a perpetual, non-exclusive, worldwide, fully paid-up, irrevocable license, with the right to sublicense through multiple levels of sublicensees, to incorporate, disclose, and use without limitation the Feedback for any purpose related to the Specification and future versions, implementations, and test suites thereof.
Any action related to this Agreement will be governed by California law and controlling U.S. federal law. The U.N. Convention for the International Sale of Goods and the choice of law rules of any jurisdiction will not apply.
The Specification is subject to U.S. export control laws and may be subject to export or import regulations in other countries. Licensee agrees to comply strictly with all such laws and regulations and acknowledges that it has the responsibility to obtain such licenses to export, re-export or import as may be required after delivery to Licensee.
This Agreement is the parties' entire agreement relating to its subject matter. It supersedes all prior or contemporaneous oral or written communications, proposals, conditions, representations and warranties and prevails over any conflicting or additional terms of any quote, order, acknowledgment, or other communication between the parties relating to its subject matter during the term of this Agreement. No modification to this Agreement will be binding, unless in writing and signed by an authorized representative of each party.