C# and Java both use modifiers to specify the accessibility and behavior of program elements. Much commonality exists between Java and C# modifiers, but many differences and inconsistencies exist as well. The differences in usage and effect are often subtle and difficult to understand and remember when coming to C# from a Java background. In this section, we contrast the Java and C# modifiers. We group these modifiers into three categories: access, inheritance, and other.
C# includes all of the access modifiers available in Java and provides additional flexibility with the introduction of two new modifiers. However, accessibility based on package membership in Java doesn’t translate to the equivalent accessibility based on namespace membership in C#. In Java, a program element with no access modifier is accessible to all members of the same package. C# has no direct equivalent; the closest match is the internal modifier. Table 4-13 contrasts the Java and C# access modifiers.
Table 4-13. Access Modifiers
Java | C# | Accessibility of Program Element |
---|---|---|
public | public | No access restrictions are enforced. Any code can access a public element. |
protected | protected | Accessible only to members of the containing class and members of derived classes. |
This is notably different from the meaning of protected in Java, which permits access by all members of the containing package and only those members outside the package that are derived from the containing class. | ||
private | private | Accessible only to members of the containing class or struct. |
N/A | internal | Accessible only to program elements contained within the same assembly. |
N/A | protected internal | The protected internal combination is the only valid combination of access modifiers. |
Accessibility is equivalent to that granted by the protected or internal modifier (in other words, it is the union of the two, not the intersection), resulting in the element being accessible to any code within the containing assembly as well as any members of the containing class or classes derived from the containing class. |
C# provides more inheritance modifiers than Java to accommodate the additional control over member inheritance provided by C#. See the Versioning and Inheritance of Members section in Chapter 5 for more details of inheritance in C#. Table 4-14 contrasts the Java and C# inheritance modifiers.
Table 4-14. Inheritance Modifiers
Java | C# | Effect on Modified Member |
---|---|---|
abstract | abstract | The abstract modifier is applicable to both classes and members of classes. Use of the abstract modifier on a class declaration identifies that the class cannot be directly instantiated. Abstract classes have a potentially incomplete implementation and are intended for use as base classes from which other classes will be derived. Use of the abstract modifier on a class declaration identifies that the class cannot be directly instantiated. Abstract classes have a potentially incomplete implementation and are intended for use as base classes from which other classes will be derived.
|
N/A | new | Explicitly confirms the intention to hide an inherited member of the same name. This behavior is not available in Java but is the default behavior applied to members in C#. Despite being the default behavior, the compiler will raise warnings if the new keyword is not used. Note that this should not be confused with the word new used in the context of object instantiation.
|
N/A | override | Specifies that the member is overriding an inherited virtual member with the same signature. Only virtual inherited members can be overridden, including those with the virtual, abstract, or override modifier.
|
final | sealed | The sealed modifier can be applied to both class and member declarations with slightly different results. Using the sealed modifier on a class declaration states that the class cannot be used as a base class for a derived class. A compile-time error will occur if this is attempted.
|
N/A | virtual | Identifies members as virtual and allows derived classes to override, as opposed to hide, inherited members. This is the default behavior in Java.
|
Table 4-15 contrasts other modifiers available in Java and C# that are unrelated to program element accessibility and inheritance.
Table 4-15. Other Modifiers
C# | Effect on Modified Member | |
---|---|---|
native | extern | Indicates that the implementation of a member is external to the C# code. This usually means that the implementation is contained in a pre-.NET Microsoft Windows dynamic-link library (DLL).
|
final | readonly | Identifies a field as being read-only. Read-only fields are more flexible than constants because they can be initialized at declaration or within an instance constructor. Static read-only fields can be initialized at declaration or within a static constructor. |
The ref and out parameter modifiers can be used only on readonly fields within the context of an instance constructor. | ||
static | static | The modified member exists within the context of the type in which it’s declared, independently of a specific class or struct instance. |
Significantly, C# static members cannot be referenced through an instance of the type, only through a reference to the containing type. | ||
Static function members have no access to the operator this. | ||
strictfp | N/A | C# has no equivalent for the strictfp modifier. |
synchronized | N/A | The C# equivalent, lock, is not used as a member modifier. See the Statements section later in this chapter and Chapter 13, for complete details. |
transient | N/A | C# does not provide a language equivalent of transient; however, the NonSerialized attribute provides comparable functionality. See Chapter 10 for full details. |
volatile | volatile | Forces synchronization and ordering of access to a field without resorting to the explicit use of lock. The field modified with the volatile modifier must be one of the following types:
|