Method and constructor overloading allows two or more methods declaration of methods or constructors with the same name to be invoked, depending on the types of their argumentsbut with different parameter lists. The compiler inspects a each call of to an overloaded method or constructor and , using uses the declared types of the method parameters , decides to decide which method to use. Consequently overloaded methods are quite usefulinvoke. In some cases, however, ambiguity confusion may arise due to because of the presence of relatively newer new language features such as autoboxing and generics.
Furthermore, methods or constructors with the same parameter types that differ only in their declaration orderings, order are typically not flagged by Java compilers. This can be potentially error prone if a developer does not Errors can result when a developer fails to consult the documentation at every each use of the a method or constructor. A related pitfall is to define differing semantics for associate different semantics with each of the overloaded methods or constructors. This Defining different semantics sometimes necessitates different orderings of the same method parameters, creating a vicious circle. Consider, for example a , an overloaded getDistance() method whose in which one overloading overloaded method returns the distance traveled from the source while another (with rearranged reordered parameters) returns the uncovered remaining distance to the destination. An implementer Implementers may not fail to realize the difference unless they consult the documentation is consulted at every use. This recommendation also applies to constructorseach use.
Noncompliant Code Example
...
(Constructor)
Constructors Notably, constructors cannot be overridden and and can only be overloaded. Failure to exercise caution while passing arguments to them can create confusion since two overloadings can contain the same number of similarly typed parameters. This noncompliant code example shows the constructor class Con with three overloadings Con(int, String), Con(String, int) and Con(Integer, String). Overloading should also be avoided when the overloaded methods provide inconsistent functionality for arguments of different types. This example violates both these conditions.overloaded constructors:
| Code Block | ||
|---|---|---|
| ||
class Con { public Con(int i, String s) { /*/ Initialization Sequence #1 */ } public Con(String s, int i) { /*/ Initialization Sequence #2 */ } public Con(Integer i, String s) { //* Initialization Sequence #3 */ } } |
Failure to exercise caution while passing arguments to these constructors can create confusion because calls to these constructors contain the same number of similarly typed actual parameters. Overloading must also be avoided when the overloaded constructors or methods provide distinct semantics for formal parameters of the same types, differing solely in their declaration order.
Compliant Solution (Constructor)
To be compliant, prefer the use of This compliant solution avoids overloading by declaring public static factory methods over having distinct names in place of the public class constructors.:
| Code Block | ||
|---|---|---|
| ||
public static voidCon ConName1createCon1(int i, String s) { /* Initialization Sequence #1 */ } public static voidCon ConName2createCon2(String s, int i) { /* Initialization Sequence #2 */ } public static voidCon ConName3createCon3(Integer i, String s) { /* Initialization Sequence #3 */ } |
Noncompliant Code Example
...
(Method)
In this noncompliant code example, the OverLoader This program provides another concrete example of noncompliance. The InformationLeak class holds a HashMap instance and returns a particular record to the caller based on either its key value in the map or the actual mapped value. The getData() method has been overloaded to return the contained data indexed by the key value in one case, whereas in the other, it checks whether a particular record exists before formatting and returning it as a String object. The InformationLeak class inherits from java.util.HashMap and overrides its get() method in order to provide the checking functionality. This implementation can be extremely confusing to the client who will expect the getData() methods to behave identically and not variably, depending on whether an index of the record is specified or the retrievable value. Worse, in the presence of autoboxing, an innocent int argument may end up invoking the undesired overloading for Integer. This can happen if the overloading with the primitive int type is added to a class at a later date. Clients who expect the getData() method to fetch data based on it's value will suddenly start invoking the new overloading whenever an int argument is passed and proceed to return the record by index. This happens because a primitive argument becomes more specific in the new version whereas in the old one, autoboxing allows the selection of the method with the Integer type parameter when an int is passed.overloaded getData() methods. One getData() method chooses the record to return on the basis of its key value in the map; the other chooses on the basis of the actual mapped value.
| Code Block | ||
|---|---|---|
| ||
class BadOverloadingOverLoader extends HashMapHashMap<Integer,Integer> { HashMap<Integer,Integer> hm; public BadOverloadingOverLoader() { hm = new HashMap<Integer, Integer>(); // hmSSN records hm.put(1, 111990000); hm.put(2, 222990000); hm.put(3, 333990000); // ssn records } public Integer getData(int i) { // overloading sequence #1 return hm.get(i); // get record at position 'i' } public String getData(Integer i) { // overloadingOverloading sequence #2#1 String s = get(i).toString(); // getGet a particular record return (s.substring(0, 3) + "-" + s.substring(3, 5) + "-" + s.substring(5, 9)); } @Override public Integer getgetData(Objectint datai) { // Overloading sequence #2 return hm.get(i); // Get record at position 'i' } // checksChecks whether the ssn exists @Override public Integer get(Object data) { // SecurityManagerCheck() for (Map.Entry<Integer, Integer> entry : hm.entrySet()) { if(entry.getValue().compareToequals((Integerdata)data) == 0){ return entry.getValue(); // exists Exists } } return null; } public static void main(String[] args) { BadOverloadingOverLoader bo = new BadOverloadingOverLoader(); // Get record at index '3' System.out.println(bo.getData(3)); // getGet record atcontaining indexdata '3111990000' System.out.println(bo.getData((Integer)111990000)); // get record containing data '111990000' } } |
| Wiki Markup |
|---|
Although the client will deduce such behavior sooner or later, other cases such as with the {{List}} interface may go unnoticed as \[[Bloch 08|AA. Java References#Bloch 08]\] describes: |
For purposes of overload resolution, the signatures of the getData() methods differ only in the static type of their formal parameters. The OverLoader class inherits from java.util.HashMap and overrides its get() method to provide the checking functionality. This implementation can be extremely confusing to the client who expects both getData() methods to behave in a similar fashion and not depend on whether an index of the record or the value to be retrieved is specified.
Although the client programmer might eventually deduce such behavior, other cases, such as with the List interface, may go unnoticed, as Joshua Bloch [Bloch 2008] describes:
The ... the
List<E>interface has two overloadings of the remove method:remove(E)andremove(int). Prior to release 1.5 when it was "generified," , theListinterface had aremove(Object)method in place ofremove(E), and the corresponding parameter types,Objectandint, were radically different. But in the presence of generics and autoboxing, the two parameter types are no longer radically different.
Consequently, a client programmer may fail to realize that the wrong element has been removed from the list.
A further problem is that in the presence of autoboxing, adding a new overloaded method definition can break previously working client code. This can happen when a new overloaded method with a more specific type is added to an API whose methods used less specific types in earlier versions. For example, if an earlier version of the OverLoader class provided only the getData(Integer) method, the client could correctly invoke this method by passing a parameter of type int; the result would be selected on the basis of its value because the int parameter would be autoboxed to Integer. Subsequently, when the getData(int) method is added, the compiler resolves all calls whose parameter is of type int to invoke the new getData(int) method, thereby changing their semantics and potentially breaking previously correct code. The compiler is entirely correct in such cases; the actual problem is an incompatible change to the API.
Compliant Solution (Method)
Naming the two related methods differently disqualifies eliminates both the overloading and is highly recommended in this situationthe confusion.
| Code Block | ||
|---|---|---|
| ||
public Integer getDataByIndex(int i) { /* overloading // sequenceNo #1 */ longer overloaded } public String getDataByValue(Integer i) { /*/ overloadingNo sequencelonger #2overloaded */ } |
...
Applicability
Ambiguous or confusing uses of overloading can lead to unexpected results.
...
Automated Detection
| Severity Tool | Likelihood Version | Remediation Cost Checker | Priority Description | Level | |
|---|---|---|---|---|---|
MET33-J | low | unlikely | high | P1 | L3 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Other Languages
This rule appears in the C++ Secure Coding Standard as DCL12-CPP. Do not allow ambiguous definitions to be mutually visible.
References
| Wiki Markup |
|---|
\[[API 06|AA. Java References#API 06]\] [Interface Collection|http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collection.html]
\[[Bloch 08|AA. Java References#Bloch 08]\] Item 41: Use overloading judiciously |
| Parasoft Jtest |
| CERT.MET50.OVERLOAD | Use overloading judiciously |
Bibliography
| [API 2013] | Interface Collection<E> |
| [Bloch 2008] | Item 41, "Use Overloading Judiciously" |
...
MET01-J. Follow good design principles while defining methods 09. Methods (MET) MET03-J. For methods that return an array or collection prefer returning an empty array or collection over a null value