Changes

826 bytes added ,  14:39, 18 June 2022
Update to 1.19
Line 4: Line 4:     
== Background ==
 
== Background ==
Java provides the mechanism of '''access level modifiers''' (or ''access modifiers''), to modify the ''visibility'' of a member with the modifier to other classes. This is commonly used to hide fields and methods from other classes, such as instance fields for [[:wikipedia:encapsulation|encapsulation]] or private methods which are part of the implementation of the class and should not be exposed to callers.
+
Java provides the mechanism of '''access level modifiers''' (or ''access modifiers''), to modify the ''visibility'' of a member with the modifier to other classes. This is commonly used to hide fields and methods from other classes, such as instance fields for [[:wikipedia:Encapsulation (computer programming)|encapsulation]] or private methods which are part of the implementation of the class and not normally exposed to callers.
    
A member can be declared with any of the modifier keywords <code>public</code>, <code>private</code>, <code>protected</code> to set the access level of the member, or none of the keywords, which defaults to a ''package-private'' access level.
 
A member can be declared with any of the modifier keywords <code>public</code>, <code>private</code>, <code>protected</code> to set the access level of the member, or none of the keywords, which defaults to a ''package-private'' access level.
Line 13: Line 13:  
! Access modifier
 
! Access modifier
 
! Within the same class
 
! Within the same class
 +
! Classes in the same package
 
! Subclasses
 
! Subclasses
! Classes in the same package
   
! All other classes
 
! All other classes
 
|-
 
|-
Line 55: Line 55:  
One solution is to use Java [[:wikipedia:reflection|reflection]] to reflectively access these fields and methods during runtime, but they suffer from some problems:
 
One solution is to use Java [[:wikipedia:reflection|reflection]] to reflectively access these fields and methods during runtime, but they suffer from some problems:
 
* Reflection is slower than regular method calls or field accesses, as certain optimizations done by the JVM cannot be applied.<ref>[https://docs.oracle.com/javase/tutorial/reflect/index.html The Java™ Tutorials: The Reflection API]: ''"Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications."''</ref> This makes reflection unsuitable for performance-critical code, such as during rendering.
 
* Reflection is slower than regular method calls or field accesses, as certain optimizations done by the JVM cannot be applied.<ref>[https://docs.oracle.com/javase/tutorial/reflect/index.html The Java™ Tutorials: The Reflection API]: ''"Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications."''</ref> This makes reflection unsuitable for performance-critical code, such as during rendering.
* Reflection cannot allow the modification of <code>final</code> fields which are either marked <code>static</code> or belong to a record class.<ref>[https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/reflect/AccessibleObject.html#setAccessible(boolean) Java 16 javadocs] for <code>java.lang.reflect.AccessibleObject.setAccessible(boolean)</code></ref>
+
* Reflection cannot allow the modification of <code>final</code> fields which are either marked <code>static</code> or belong to a record class.<ref>[https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/reflect/AccessibleObject.html#setAccessible(boolean) Java 17 javadocs] for <code>java.lang.reflect.AccessibleObject.setAccessible(boolean)</code></ref>
 
* Runtime reflection loses the benefit of compile-time type checks, which allows dangerous operations such as trying to set a field's value to an incompatible type.
 
* Runtime reflection loses the benefit of compile-time type checks, which allows dangerous operations such as trying to set a field's value to an incompatible type.
 
* The use of reflection does not allow a class to extend a non-visible class.
 
* The use of reflection does not allow a class to extend a non-visible class.
Line 101: Line 101:  
The class name is the fully qualified name of the class, using <code>.</code> (dots) to separate between (sub)packages and classes (for example, <code>java.lang.Object</code>).  
 
The class name is the fully qualified name of the class, using <code>.</code> (dots) to separate between (sub)packages and classes (for example, <code>java.lang.Object</code>).  
   −
For methods, the method descriptor<ref>''[https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-4.html#jvms-4.3.3 Java Virtual Machine Specification, Java SE 16 Edition]'', 4.3.3. Method Descriptors </ref> of the method is included, which consists of the descriptors for each of the method's parameters and the method's return type. The method parameters descriptors can be absent if there are no parameters in the method, but the return type descriptor must be present.
+
For methods, the method descriptor<ref>''[https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html#jvms-4.3.3 Java Virtual Machine Specification, Java SE 17 Edition]'', 4.3.3. Method Descriptors </ref> of the method is included, which consists of the descriptors for each of the method's parameters and the method's return type. The method parameters descriptors can be absent if there are no parameters in the method, but the return type descriptor must be present.
    
The following are the matching descriptors for each type as seen in the method declaration:
 
The following are the matching descriptors for each type as seen in the method declaration:
Line 128: Line 128:  
| <code>[''I''</code> || <code>''int''[]</code> || one dimension of an array; this can be repeated, and must end with another descriptor other than an array
 
| <code>[''I''</code> || <code>''int''[]</code> || one dimension of an array; this can be repeated, and must end with another descriptor other than an array
 
|-
 
|-
| <code>L''java/lang/Object'';</code> || <code>java.lang.Object</code> || a reference type; the internal form of the class' binary name must be present (in the given example, the class referenced is <code>java.lang.Object</code>.  
+
| <code>L''java/lang/Object'';</code> || <code>java.lang.Object</code> || a reference type; the internal form of the class' binary name must be present (in the given example, the class referenced is <code>java.lang.Object</code>).  
 
Note that inner classes are separated using the <code>$</code> (dollar sign) character, such as <code>java/lang/System$Logger</code>.
 
Note that inner classes are separated using the <code>$</code> (dollar sign) character, such as <code>java/lang/System$Logger</code>.
 
|-
 
|-
 
| <code>V</code> || <code>void</code> || a void or no-value return type; only available for the return type of a method descriptor
 
| <code>V</code> || <code>void</code> || a void or no-value return type; only available for the return type of a method descriptor
 
|}
 
|}
 +
 +
{{Tip/Danger
 +
|title=Wildcard access transformers
 +
|A special type of access transformers called '''wildcard ATs''' (oftentimes referred to as '''shotgun ATs''' allows transforming the access modifier and finality of ''all'' fields or methods within a class.
 +
 +
To use wildcard access transformers:
 +
* for all methods within a class: <code>''<modifier>'' ''<class name>'' '''*()'''</code>
 +
* for all fields within a class: <code>''<modifier>'' ''<class name>'' '''*'''</code>
 +
 +
'''Modders should avoid using this in live code.''' Access transformers should always have the fewest and narrowest targets possible, and wildcard ATs violate this convention. Use of wildcard ATs may cause problems with both the ForgeGradle setup process. Wildcard ATs may be removed in a future update of the access transformer specification.
 +
}}
    
== Examples ==
 
== Examples ==
Line 152: Line 163:  
public net.minecraft.Util m_137477_(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; # makeExecutor
 
public net.minecraft.Util m_137477_(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; # makeExecutor
   −
# Makes public the 'leastMostToIntArray' method in SerializableUUID,
+
# Makes public the 'leastMostToIntArray' method in UUIDUtil,
 
# which accepts two longs and returns an int[]
 
# which accepts two longs and returns an int[]
public net.minecraft.core.SerializableUUID m_123274_(JJ)[I # leastMostToIntArray
+
public net.minecraft.core.UUIDUtil m_235872_(JJ)[I # leastMostToIntArray
 
</syntaxhighlight>
 
</syntaxhighlight>