除了
Ewald的回答之外,这里有一个小演示,展示了基于返回类型进行重载是真正可行的。可以有一个单一的类,其中包含两个方法,它们具有相同的名称和参数,只有返回类型不同。
(这是一个纯Java程序的事实,模糊了语言和JVM之间的边界,使得回答“Java”是否允许这种重载变得更加困难,但我认为Ewald已经解释得很好了 - 当然,我为这个演示“作弊”... :))
该程序使用
Apache ByteCode Engineering Library (BCEL)在运行时生成和加载这样的类。然后,它创建此类的实例,并列出并调用所有(声明的)方法。
package stackoverflow.returntypes;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.PUSH;
import org.apache.bcel.generic.Type;
public class DifferentReturnTypesDemo
{
public static void main(String[] args) throws Exception
{
ClassGenerator classGenerator = new ClassGenerator();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
classGenerator.create(baos);
ByteArrayClassLoader byteArrayClassLoader = new ByteArrayClassLoader(
baos.toByteArray());
Class<?> c = byteArrayClassLoader.loadClass(
"stackoverflow.returntypes.Generated");
byteArrayClassLoader.close();
Object instance = c.newInstance();
for (Method method : c.getDeclaredMethods())
{
System.out.println(method);
method.invoke(instance, (Object[]) null);
}
}
}
class ByteArrayClassLoader extends URLClassLoader
{
private final byte data[];
ByteArrayClassLoader(byte data[])
{
super(new URL[0]);
this.data = data;
}
@Override
protected Class<?> findClass(final String name)
throws ClassNotFoundException
{
return defineClass(name, data, 0, data.length);
}
}
class ClassGenerator
{
private InstructionFactory instructionFactory;
private ConstantPoolGen constantPool_cp;
private ClassGen classGen;
public ClassGenerator()
{
classGen = new ClassGen("stackoverflow.returntypes.Generated",
"java.lang.Object", "Generator.java", Constants.ACC_PUBLIC |
Constants.ACC_SUPER, new String[] {});
constantPool_cp = classGen.getConstantPool();
instructionFactory = new InstructionFactory(classGen, constantPool_cp);
}
public void create(OutputStream out) throws IOException
{
createCreateConstructor();
createMethodReturningInt();
createMethodReturningFloat();
classGen.getJavaClass().dump(out);
}
private void createCreateConstructor()
{
InstructionList instructionList = new InstructionList();
MethodGen method = new MethodGen(Constants.ACC_PUBLIC, Type.VOID,
Type.NO_ARGS, new String[0], "<init>",
"stackoverflow.returntypes.Generated", instructionList,
constantPool_cp);
instructionList.append(InstructionFactory.createLoad(Type.OBJECT, 0));
instructionList.append(instructionFactory.createInvoke(
"java.lang.Object", "<init>", Type.VOID, Type.NO_ARGS,
Constants.INVOKESPECIAL));
instructionList.append(InstructionFactory.createReturn(Type.VOID));
method.setMaxStack();
method.setMaxLocals();
classGen.addMethod(method.getMethod());
instructionList.dispose();
}
private void createMethodReturningInt()
{
InstructionList instructionList = new InstructionList();
MethodGen method = new MethodGen(Constants.ACC_PUBLIC, Type.INT,
Type.NO_ARGS, new String[0], "print",
"stackoverflow.returntypes.Generated", instructionList,
constantPool_cp);
instructionList.append(instructionFactory.createFieldAccess(
"java.lang.System", "out", new ObjectType("java.io.PrintStream"),
Constants.GETSTATIC));
instructionList.append(new PUSH(constantPool_cp, "return int"));
instructionList.append(instructionFactory.createInvoke(
"java.io.PrintStream", "println", Type.VOID,
new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
instructionList.append(new PUSH(constantPool_cp, 123));
instructionList.append(InstructionFactory.createReturn(Type.INT));
method.setMaxStack();
method.setMaxLocals();
classGen.addMethod(method.getMethod());
instructionList.dispose();
}
private void createMethodReturningFloat()
{
InstructionList instructionList = new InstructionList();
MethodGen method = new MethodGen(Constants.ACC_PUBLIC, Type.FLOAT,
Type.NO_ARGS, new String[0], "print",
"stackoverflow.returntypes.Generated", instructionList,
constantPool_cp);
instructionList.append(instructionFactory.createFieldAccess(
"java.lang.System", "out", new ObjectType("java.io.PrintStream"),
Constants.GETSTATIC));
instructionList.append(new PUSH(constantPool_cp, "return float"));
instructionList.append(instructionFactory.createInvoke(
"java.io.PrintStream", "println", Type.VOID,
new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
instructionList.append(new PUSH(constantPool_cp, 456.789f));
instructionList.append(InstructionFactory.createReturn(Type.FLOAT));
method.setMaxStack();
method.setMaxLocals();
classGen.addMethod(method.getMethod());
instructionList.dispose();
}
}
输出是
public int stackoverflow.returntypes.Generated.print()
return int
public float stackoverflow.returntypes.Generated.print()
return float
显示同名签名的方法出现了两次,只是返回类型不同-并且使用反射,仍然可以调用这两个方法。