This question already has an answer here:
-
Generic type parameter naming convention for Java (with multiple chars)?
5 answers
I have an interface whose declaration is as follows:
/**
* @param T - the type of entity.
* @param C - the type of entity container will be returned.
*/
public interface FindByNamedQuery<T extends Serializable, C extends Collection<T>> extends Command {
C executeNamedQuery(String namedQuery);
}
I wonder if I can (should) break the Java naming convention to do this:
public interface FindByNamedQuery<ENTITY_TYPE extends Serializable, RETURNED_CONTAINER extends Collection<ENTITY_TYPE>> extends Command {
RETURNED_CONTAINER executeNamedQuery(String namedQuery);
}
I am beginning to disagree with the single-character convention, after using it since the mid-1990s.
I find the readable names more readable. This is helpful in understanding both the implementation and interface of generic types.
The ambiguity problem seems overstated for Java. Few class names are all-uppercase. Constants are not used in the same context as class names.
It's true that the @param JavaDoc elements can provide a longer description. But it's also true that the JavaDocs are not necessarily visible. (For example, there's a content assist in Eclipse that shows the type parameter names.)
For example, compare :
public final class EventProducer<L extends IEventListener<E>,E>
implements IEventProducer<L,E> {
to:
public final class EventProducer<LISTENER extends IEventListener<EVENT>,EVENT>
implements IEventProducer<LISTENER, EVENT> {
Although the single-character names have been recommended as a convention by Sun/Oracle, conventions can be changed. The consequences of challenging this convention are minor. If you and your team prefer meaningful names for your type parameters, I personally would go for it.
Edit (2015)
Google style for Java allows both single-letter names and multi-character class-like names ending in T.
5.2.8 Type variable names
Each type variable is named in one of two styles:
A single capital letter, optionally followed by a single numeral (such as E, T, X, T2)
A name in the form used for classes (see Section 5.2.2, Class names), followed by the capital letter T (examples: RequestT,
FooBarT).
I wonder if I can (should) break the java naming convention to do this:
No, this should be avoided as it becomes easier to confuse the type parameters with constants and other identifiers.
Here's a quote from the official trail on generics:
Type Parameter Naming Conventions
By convention, type parameter names are single, uppercase letters. This stands in sharp contrast to the variable naming conventions that you already know about, and with good reason: Without this convention, it would be difficult to tell the difference between a type variable and an ordinary class or interface name.
The most commonly used type parameter names are:
E
- Element (used extensively by the Java Collections Framework)
K
- Key
N
- Number
T
- Type
V
- Value
S
,U
,V
etc. - 2nd, 3rd, 4th types
You'll see these names used throughout the Java SE API and the rest of this tutorial.
Using TDescription is pretty common in C#. It maintains the T name but is also descriptive at the same time, like so:
public interface FindByNamedQuery<
TEntityType extends Serialiazble,
TReturnedContainer extends Collections<TEntityType>> extends Command
{
TReturnedContainer executeNamedQuery(String namedQuery);
}
As others have said ALL_CAPS
almost always indicates a constant.
IMO, "it would be difficult to tell the difference between a type variable and an ordinary class or interface name." does not apply here, because the T prefix easily identifies it as a type variable.
Again, this is C# but see MSDN: Naming Conventions For Generics
In all other cases, the official
Microsoft guidelines for generic
naming conventions are:
Name generic type parameters with descriptive names, unless a single
letter name is completely self
explanatory and a descriptive name
would not add value.
public interface ISessionChannel<TSession>
{...}
public delegate TOutput Converter<TInput,TOutput>(TInput from);
- Consider indicating constraints placed on a type parameter in the name of parameter. For example, a parameter constrained to ISession may be called TSession.
The compiler might not complain, but your teammates might not appreciate you using what looks to be a constant in a place where they're expecting a type parameter.
I think this is the gripe of many people using generics. I don't quite agree with Sun's statement that if you use a full fledged name then it will confuse with an existing class name or something else. In that case we can start the placeholder name with a dollar like this:
public class HashMap<$Key,$Value> implements Map<$Key,$Value>{}
No one in their sane mind names a class starting with a dollar sign. And a dollar sign also is used to denote a placeholder many templating languages velocity, struts, spring, etc. I think this is the way to go.
I have got more details about this and the reasoning behind not having to use a single letter notation in my blog post if anyone is interested.
http://readsethu.wordpress.com/2012/05/23/a-generic-class-and-why-is-it-confusing/
Like Allen before, my advice comes more from C# (which I use extensively since 5 months) than Java (which I played with, but it never went very far...), but I find Java and C# code quite similar in spirit (that is, when compared by, say, C++)
Anyway, when using a C#/Java generic (or a C++ template) on a simple type, I usually use T:
// C++
template<typename T>
class MyClass { /* ... */ } ;
// C#
public MyClass<T> { /* etc. */ }
// Java
public MyClass<T> { /* etc. */ }
Usually, the type T goes with the class, so there is no need to describe it more.
But when really describing the type adds to the code clarity, I do it.
Or when I have two or more types in the same generic/template declaration, it helps to make the difference between two types. For example (real life example in C#) :
// C++
template<typename T_Data, typename T_Underlying>
class MyClass { /* ... */ } ;
// C#
public MyClass<T_Data, T_Underlying> { /* etc. */ }
// Java
public MyClass<T_Data, T_Underlying> { /* etc. */ }
This way, it is easy to make the difference between the two typenames in the code, where T
and U
are, well... kinda anonymous: For those using Visual C++, going in debug inside Dinkumware's STL code, full of T
, _U
, and other mono-letter typenames can be quite frustrating... I guess the same goes for C# or Java code.
You will note that in each case (C++, Java or C#), I don't follow the convention somewhere in my type namings: The reason is that sometimes, you just have to try something else instead of following the herd, even if in the end, you'll find you're wrong.
In the current case, the violation of naming convention is not critical (there are worst problems in Java than this petty crime), and at the very last, you'll learn personally and exactly WHY it is wrong, instead of quoting old documents.
And if you find in the end you're right, well...
I would name type variables similar to types, in camel casing, but prefixed with "_".
public interface FindByNamedQuery
<_EntityType extends Serialiazble,
_ReturnedContainer extends Collections<_EntityType>>
extends Command
{
_ReturnedContainer executeNamedQuery(String namedQuery);
}