我最近遇到了java @SafeVarargs注释.谷歌搜索使Java中的可变函数不安全的原因让我感到困惑(堆中毒?擦除类型?),所以我想知道一些事情:
是什么让可变参数Java函数在@SafeVarargs意义上不安全(最好以深入的例子的形式解释)?
为什么这个注释留给程序员自行决定?这不是编译器应该能够检查的东西吗?
是否有必须坚持一些标准,以确保他的功能确实安全?如果没有,确保它的最佳做法是什么?
我不确定我在这里使用的词汇,如果我错了,请纠正我.
在Javascript中,我有以下代码:
let args = [1,2,3];
function doSomething (a, b, c) {
return a + b + c;
}
doSomething(...args);
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,在调用时doSomething,我能够使用...spread运算符来"转换"我的参数1, 2, 3.
现在,我正在尝试用Java做同样的事情.
假设我有一Foo节课:
public class Foo {
public int doSomething (int a, int b, int c) {
return a + b + c;
}
}
Run Code Online (Sandbox Code Playgroud)
现在我想打电话给doSomething:
int[] args = {1, 2, 3};
Run Code Online (Sandbox Code Playgroud)
我想用一些东西doSomething (...args)而不是打电话doSomething(args[0], args[1], args[2]).
我看到这在函数声明中是可能的,但我不想改变这样一个函数的实现.
Google使用varargs参数的原因是什么AsyncTask?例如,方法execute(),doInBackground()以及publishProgress()所有使用[Type]...的符号.
我认为这使得"更难"使用,所以他们必须有一些我忽略的好理由?
所以,要么我们没有参数,要么有一个或多个参数.让我们分解一下:
没有参数(简单):Params参数是Void,就是这样.(这些方法不能使用它......所以非常安全.)
一个参数:至少在这里,我觉得有必要在doInBackground()方法的开头进行检查.例如,这是一个接收Integer和生成类型结果的任务Double:
public Double doInBackground(Integer... myParameters) {
// we are only expecting one parameter
if (myParameters.length != 1)
throw new IllegalArgumentException("!= 1");
return 100d * myParameters[0];
}
Run Code Online (Sandbox Code Playgroud)多个参数.现在这里必须是Google做出正确选择的地方吗?但正如我所看到的那样,您要么对相同类型的参数列表感兴趣,要么需要不同类型的参数.谷歌只解决了其中一种情况(不同类型你需要某种通用界面.在很多情况下,我最终Object...得到的并不是真正的类型安全......)
那么,如果我们完全删除它会有什么问题varargs呢?这是方法的一个子集:
class AsyncTask<Param, Progress, Result> {
abstract Result doInBackground(Param param);
void publishProgress(Progress progress) { ... } …Run Code Online (Sandbox Code Playgroud) class WrongOverloading{
void something(String [] a){ .. }
Integer something(String... aaa){ return 1;}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码不能编译!编译器说这些是重复的方法.那么使用String数组或String var-args是否完全相同?
它们是如何在内部实施的?
以下Python片段完全符合我的意思:
def function(a, b, c):
print("%i :: %s :: %f" % (a,b,c))
a = 1
b = "abc"
c = 1.0
function(a, b, c)
list = [a, b, c]
# This is what I am searching for in Java
function(*(list))
Run Code Online (Sandbox Code Playgroud)
所以我有一个类似列表的结构,我不知道它有多少个参数,但我知道它有正确数量的参数和正确的类型和格式.我想把它们传递给一个方法.所以我必须"扩大"这些论点.有人知道如何在Java中这样做吗?
我正在参加一个数据结构和算法课程,以获得当地社区大学的乐趣.该课程的教科书是Y. Daniel Liang的Java编程入门,第10版.这本书本身非常扎实.
在处理时Java.util.Arrays,Liang提到了Java的"可变长度"参数.他写道(第265页):
Java将可变长度参数视为数组.您可以将数组或可变数量的参数传递给可变长度参数.当调用具有可变数量参数的方法时,Java会创建一个数组并将参数传递给它.
一个例子是:
public static void (int... toes) {
//... some code
}
Run Code Online (Sandbox Code Playgroud)
然而,梁从未解释变长参数的起源或优势.如果像梁说的那样,将可变长度参数"转换"为数组,那么它们的优势是什么?是否有可变长度参数促进的软件设计模式或工程目标?
换句话说,上面的代码片段提供的内容不是由以下内容提供的:
public static void (int[] toes) { // ...
Run Code Online (Sandbox Code Playgroud) 所以我一直试图找出String...Java中的重点.根据我的理解,它与String []大致相同,但我无法在此处或在Google上找到有关它的任何信息.
有人可以告诉我它是什么以及这样的东西的正确用法吗?(假设我有一个带参数的方法myMethod(String... args) { ... }
谢谢!
它非常重载,所有元素的数量从1到10 ...
它说:
返回包含五个元素的不可修改列表。
有关详细信息,请参见不可修改的列表。
类型参数:E-列表的元素类型参数:e1-第一个元素e2-第二个元素e3-第三个元素e4-第四个元素e5-第五个元素
我只是一点都不了解,可以找到一种使用它的方法吗?
我第一次...在方法签名中看到它.
我试图访问.class文件.它有一个定义如下的方法
public void addGraphData(GraphData... _graphData) {
}
Run Code Online (Sandbox Code Playgroud)
而GraphData只不过是带有getter和setter的POJO.为什么显示.class文件GraphData... _graphData而不是GraphData _graphData?
作为两个功能
foo(Object... obj)
{
for(int i=0;i<obj.length;i++)
System.out.println(obj[i]);
}
Run Code Online (Sandbox Code Playgroud)
和
foo(Object [] obj)
{
for(int i=0;i<obj.length;i++)
System.out.println(obj[i]);
}
Run Code Online (Sandbox Code Playgroud)
并且可以完成函数调用
FOO(OBJ,STR,1);
FOO({OBJ,STR,1});
分别执行相同的功能,后者从java的开始就存在,然后为什么实现Object ... obj
哪一个更好,为什么?
在我的一生中,我一直在想这两者之间的区别是什么,差异在于
public static void main (String[] args){}
Run Code Online (Sandbox Code Playgroud)
和
static public void main(String... args){}
Run Code Online (Sandbox Code Playgroud)
我和我的朋友见过这些代码,但即使他也不知道原因.
这两者如何相互不同?
抱歉,我编辑了主方法的返回类型...
我一直在做一堆研究并查看Android中ASyncTask的文档,但我似乎无法绕过它.我只是想在一个片段在应用程序中可见时运行一些方法,但为了更容易做到这一点,我想我应该使用ASyncTask.我的示例代码如下:
private class syncExample extends ASyncTask <Void, Void, Void>
{
@Override
protected void onPreExecute()
{
}
@Override
protected void doInBackground(Void... voids)
{
}
@Override
protected void onProgressUpdate()
{
}
@Override
protected void onPostExecute()
{
}
}
Run Code Online (Sandbox Code Playgroud)
现在我的问题如下:
在尖括号中,我有Void,Void,Void.这些代表到底是什么,我怎么知道在那里放置什么是正确的?
对于类中的每个方法,我将每个方法称为void.它们何时应该与void不同(如boolean,String,long等)?
对于doInBackground方法,我在括号中有Void ...空格.我究竟应该把它放在那里?它们代表什么?
谢谢您的帮助.关于这个的文档对于像我这样的初学者来说并不是很清楚.
我有这个AVL树与平衡方法:
private void setBalance(Node... nodes) {
for (Node n : nodes)
n.height = height(n.right) - height(n.left);
}
Run Code Online (Sandbox Code Playgroud)
它使用我之前没有遇到过的(...)语法.我无法在谷歌或SO上找到它.它似乎是某种类型的列表语法或数组.看起来像我会在红宝石中找到的东西.
知道Java语法的人是否可以向我解释这个代码,并且可能会向我展示一个没有...语法的版本?
谢谢.