Api Java标准库:库中哪些方法的参数最多?
在Java标准库中,哪些方法具有最多的参数 注意:变量参数(Varargs)应计为数组类型的1个参数,而不是无限多个参数 原因:我正在尝试设计更好的库,我正在考虑禁止使用超过4个参数的方法,也许。。。Api Java标准库:库中哪些方法的参数最多?,api,api-design,java,library-design,Api,Api Design,Java,Library Design,在Java标准库中,哪些方法具有最多的参数 注意:变量参数(Varargs)应计为数组类型的1个参数,而不是无限多个参数 原因:我正在尝试设计更好的库,我正在考虑禁止使用超过4个参数的方法,也许。。。 因此,我试图在标准库中找到具有大量参数的方法,研究该方法,并思考是否需要这样定义,以及是否有一个有效的案例具有4个以上的参数。对于实际提出的问题,我没有答案,但我确实认为我对潜在的问题有一些有用的见解你们试图回答的问题 这里我要提到的是,平均每个人一次可以记住7件事(注意北美当地的电话号码是7位数
因此,我试图在标准库中找到具有大量参数的方法,研究该方法,并思考是否需要这样定义,以及是否有一个有效的案例具有4个以上的参数。对于实际提出的问题,我没有答案,但我确实认为我对潜在的问题有一些有用的见解你们试图回答的问题 这里我要提到的是,平均每个人一次可以记住7件事(注意北美当地的电话号码是7位数) <>这意味着,当你看到大约7的东西时,你应该考虑打破和使用构图。例如:
- 每包7节课
- 每个接口7种方法
- 函数的7个参数
- 使用多个接口(特别是如果您可以看到分离,或者有机会遵守接口分离原则
- 为包中的一个子类创建子包或新的顶级包
- 利用Helper类,它可以帮助吸收函数的一些参数
这是灵活的(例如,法律规定它实际上是+2或-2)但我认为它可以作为一个有用的基准。限制自己的公共API中参数数量的目标当然是一个好的目标,但人们不应该盲目地遵守任意规则,然后应用古怪的变通方法来遵循它们。而且,有时应该只是如何不解决某些问题的启发
也就是说,回答实际问题有点困难。你想
- 只关注
或公共
方法受保护的
- 在类中包含JavaFX之类的方法
- 在
类中包含方法,但包含专有API公共的
然而,我很好奇。使用(+1!)、加载它们(并公然忽略错误)、从有效类中获取所有方法并查看它们的参数计数,我可以找到一些结果:
- 总的赢家似乎来自JavaFX运行时的一个类,名为
。该方法是一个com.sun.scenario.effect.impl.sw.sse.SSEPhongLighting\u SPOTPeer
方法,简单地称为本机
,并接收到一个巨大的37个参数:过滤器
但是,该方法是私有静态本机void com.sun.scenario、 effect.impl.sw.sse.SSEPhongLighting_SPOTPeer.filter(int[],int,int,int,int,int,int[],float,float,float,float,int,int,int,int,int,int,int,float,float,float,float,float,int[],float,float,float,float,float,float,int,int,float,float,float)
和private
,在OpenJDK JavaFX运行时repo中甚至找不到该类,因此我假设它是以某种方式自动生成的native
- 将整个搜索限制为
类和方法,这些类和方法也是public
或public
(而不是受保护的
)这一次,它在本机的
类中,它有一个名为com.sun.prism.impl.VertexBuffer
的方法,有24个参数:addMappedPgram
,回购协议还包含 这是一个大多数编码准则都会说参数数量太多的方法示例。但是参数太“常规”(遵循命名模式,可能与四边形的4个角有关)我认为这样的东西仍然是合理的,但是这个类仍然不应该被客户端使用,必须被视为“专有API”public final void com.sun.prism.impl.VertexBuffer.addMappedPgram(浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动、浮动)
- 省略以
或“sun.”
将我们带到可能被认为是“正确答案”的地方问题:类“com.sun.”开头的包中的类。
包含一个名为org.w3c.dom.events.MouseEvent
的方法,该方法仍然接收15个参数:initMouseEvent
public abstract void org.w3c.dom.events.MouseEvent.initMouseEvent(java.lang.String、boolean、boolean、org.w3c.dom.views.AbstractView、int、int、int、int、boolean、boolean、short、org.w3c.dom.events.EventTarget)
javafx.scene.input.ScrollEvent
有两个构造函数,其中23个参数,即public javafx.scene.input.ScrollEvent(javafx.event.EventType、double、double、double、boolean、boolean、double、double、double、double、double、double、double、javafx.scene.input.ScrollEvent$HorizontalTextScrollUnits、double、int、javafx.scene.input.PickResult)
和公共javafx.scene.input.ScrollEvent(java.lang.Object,java
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.function.Predicate;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class ArgCounting
{
static class Entry
{
Class<?> clazz;
Executable executable;
int numParams;
}
public static void main(String[] args) throws Exception
{
List<Entry> entries = new ArrayList<Entry>();
ClassFinder.findClasses(new Visitor<String>()
{
@Override
public boolean visit(String clazz)
{
try
{
System.out.println(clazz);
Class<?> c = Class.forName(clazz);
Method[] methods = c.getDeclaredMethods();
for (Method method : methods)
{
Entry entry = new Entry();
entry.clazz = c;
entry.executable = method;
entry.numParams = method.getParameterCount();
entries.add(entry);
}
Constructor<?>[] constructors = c.getDeclaredConstructors();
for (Constructor<?> constructor : constructors)
{
Entry entry = new Entry();
entry.clazz = c;
entry.executable = constructor;
entry.numParams = constructor.getParameterCount();
entries.add(entry);
}
}
catch (Throwable e)
{
System.out.println("Ignoring: " + e);
}
return true;
}
});
System.out.println("There are " + entries.size() + " executables");
Predicate<Entry> executableIsNotNative =
e -> !Modifier.isNative(e.executable.getModifiers());
Predicate<Entry> executableIsPublic =
e -> Modifier.isPublic(e.executable.getModifiers());
Predicate<Entry> executableIsProtected =
e -> Modifier.isProtected(e.executable.getModifiers());
Predicate<Entry> classIsPublic =
e -> Modifier.isPublic(e.clazz.getModifiers());
List<String> skippedPackagePrefixes = Arrays.asList(
"sun.", "com.sun.");
Predicate<Entry> isSkipped = e ->
{
for (String prefix : skippedPackagePrefixes)
{
Package p = e.clazz.getPackage();
if (p != null)
{
if (p.getName().startsWith(prefix))
{
return true;
}
}
}
return false;
};
Predicate<Entry> isNotSkipped = isSkipped.negate();
Predicate<Entry> executableIsRelevant =
executableIsNotNative.and(executableIsPublic.or(executableIsProtected));
System.out.println("Methods:");
printAllMax(entries,
classIsPublic.and(executableIsRelevant).and(isNotSkipped).and(e -> e.executable instanceof Method));
System.out.println("Constructors:");
printAllMax(entries,
classIsPublic.and(executableIsRelevant).and(isNotSkipped).and(e -> e.executable instanceof Constructor));
}
private static void printAllMax(Collection<Entry> entries, Predicate<Entry> filter)
{
int max = entries.stream()
.filter(filter)
.mapToInt(e -> e.numParams)
.max()
.getAsInt();
System.out.println("Having " + max + " parameters:");
entries.stream().filter(filter.and(e -> e.numParams == max)).forEach(e ->
{
System.out.println(e.executable);
});
}
}
// From https://stackoverflow.com/a/19554704/3182664
interface Visitor<T>
{
/**
* @return {@code true} if the algorithm should visit more results,
* {@code false} if it should terminate now.
*/
public boolean visit(T t);
}
// From https://stackoverflow.com/a/19554704/3182664
class ClassFinder
{
public static void findClasses(Visitor<String> visitor)
{
String classpath = System.getProperty("java.class.path");
String[] paths = classpath.split(System.getProperty("path.separator"));
String javaHome = System.getProperty("java.home");
File file = new File(javaHome + File.separator + "lib");
if (file.exists())
{
findClasses(file, file, true, visitor);
}
for (String path : paths)
{
file = new File(path);
if (file.exists())
{
findClasses(file, file, false, visitor);
}
}
}
private static boolean findClasses(File root, File file,
boolean includeJars, Visitor<String> visitor)
{
if (file.isDirectory())
{
for (File child : file.listFiles())
{
if (!findClasses(root, child, includeJars, visitor))
{
return false;
}
}
}
else
{
if (file.getName().toLowerCase().endsWith(".jar") && includeJars)
{
JarFile jar = null;
try
{
jar = new JarFile(file);
}
catch (Exception ex)
{
}
if (jar != null)
{
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements())
{
JarEntry entry = entries.nextElement();
String name = entry.getName();
int extIndex = name.lastIndexOf(".class");
if (extIndex > 0)
{
if (!visitor.visit(
name.substring(0, extIndex).replace("/", ".")))
{
return false;
}
}
}
}
}
else if (file.getName().toLowerCase().endsWith(".class"))
{
if (!visitor.visit(createClassName(root, file)))
{
return false;
}
}
}
return true;
}
private static String createClassName(File root, File file)
{
StringBuffer sb = new StringBuffer();
String fileName = file.getName();
sb.append(fileName.substring(0, fileName.lastIndexOf(".class")));
file = file.getParentFile();
while (file != null && !file.equals(root))
{
sb.insert(0, '.').insert(0, file.getName());
file = file.getParentFile();
}
return sb.toString();
}
}