GVKun编程网logo

没有传递参数或null时的Java 3点参数(varargs)行为(java没有引用传递 只有值传递)

5

以上就是给各位分享没有传递参数或null时的Java3点参数,其中也会对varargs行为进行解释,同时本文还将给你拓展(十五)python3可变长参数(arg,*args,**kwargs)、C++

以上就是给各位分享没有传递参数或null时的Java 3点参数,其中也会对varargs行为进行解释,同时本文还将给你拓展(十五) python3 可变长参数(arg,*args,**kwargs)、C++解析命令行参数(仿C语言args)、Java Varargs 可变参数使用、Java Varargs 可变参数用法详解等相关知识,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

没有传递参数或null时的Java 3点参数(varargs)行为(java没有引用传递 只有值传递)

没有传递参数或null时的Java 3点参数(varargs)行为(java没有引用传递 只有值传递)

我尝试过这个,并从JAVA中得到了奇怪的行为,有人可以帮我解释一下吗?

boolean testNull(String... string) {    if(string == null) {        return true;    } else {        System.out.println(string.getClass());        return false;    }}boolean callTestNull(String s) {    return testNull(s);}

然后我有测试用例:

    @Test    public void test_cases() {        assertTrue(instance.testNull(null)); // NULL        assertFalse(instance.testNull()); // NOT NULL        assertFalse(instance.callTestNull(null)); // NOT NULL    }

现在的问题是,如果我打电话testNull()直接与参数null,我会true回来,但如果调用callTestNull()null,它调用testNull(),它告诉我该参数不为空,但空数组。

答案1

小编典典

问题是,如果我直接使用参数null调用testNull(),我会回来,但如果使用null调用callTestNull()调用了testNull(),它将告诉我参数不是null,而是空数组。

是。如果使用 编译时类型 为的参数调用它String,则编译器会知道它 不能String[],因此会将其包装在字符串数组中。所以这:

String x = null;testNull(x);

等效于:

String x = null;testNull(new String[] { x });

在这一点上,(具有误导性的)string参数将具有非null值-相反,它将引用大小为1的数组,其唯一元素是null引用。

但是,当您null直接在方法调用中使用文字时,它可以直接转换为String[],因此不执行任何包装。

从JLS第15.12.4.2节开始:

如果要调用的方法是可变Arity方法m,则它必须具有n> 0形式参数。对于某些T,m的最终形式参数必须具有T
[]类型,并且必须使用k≥0的实际参数表达式来调用m。

如果m用k≠n个实际参数表达式调用,或者m用k = n个实际参数表达式调用,并且第k个参数表达式 的类型与T []分配不兼容
,则参数列表(e1,…,en-1,en,…,ek)的计算方式就像(e1,…,en-1,new | T [] | {en,…
,ek}),其中| T [] | 表示T []的擦除(第4.6节)。

(强调我的。)

我强调的一点是为什么 在参数的编译时类型为而String不是null类型 时才 进行换行。

(十五) python3 可变长参数(arg,*args,**kwargs)

(十五) python3 可变长参数(arg,*args,**kwargs)

 可变长参数(*args,**kwargs)

一、最常见的是在定义函数时,预先并不知道,函数使用者会传递多少个参数给你,所以在这个场景下使用这两个关键字。其实并不是必须写成 * args 和 **kwargs。  *(星号) 才是必须的。你也可以写成 * ar 和 **k. 而写成 * args 和 **kwargs 只是一个通俗的命名约定。分别代表的是元组和字典

def x(arg, *args, **kwargs):
    print(''arg--> {}''.format(arg))
    print(''args--> {} ''.format(args))
    print(''kwarg--> {} ''.format(kwargs))


x(1,2,3,4,key1="value1")

#结果
# arg--> 1
# args--> (2, 3, 4) 
# kwarg--> {''key1'': ''value1''}

  在函数调用时,位置参数传递必须在关键字参数左边或者说前面,**kwargs 接收关键字参数,生成字典。*args 接收除第一个位置参数和关键字参数外的其它参数生成元组,根参数是什么数据类型无关。

 

def x(arg, *args, **kwargs):
    print(''arg--> {}''.format(arg))
    print(''args--> {} ''.format(args))
    print(''kwarg--> {} ''.format(kwargs))


x(1,(2,3,),4,key1="value1")

#arg--> 1
#args--> ((2, 3), 4) 
#kwarg--> {''key1'': ''value1''}

 

二、函数调用时使用 * args、**args

 下面方式调用应该不难理解

def print_info(name,age,sex):
    print(''name--> {}''.format(name))
    print(''age--> {} ''.format(age))
    print(''sex--> {} ''.format(sex))


print_info("name1",25,"男")

#name--> name1
# age--> 25 
# sex--> 男

 换个方式:*args,**kwargs

def print_info(name, age, sex):
    print(''name--> {}''.format(name))
    print(''age--> {} ''.format(age))
    print(''sex--> {} ''.format(sex))


list = ["李刚", 20, "男"]

dic = {"name": "王某某", "age": 30, "sex": "女",}

print_info(*list)

# 将列表或元组前加“*”并传组函数,(注意:元素个数与位置必须对应)结果如下。
# name--> 李刚
# age--> 20
# sex--> 男



print_info(**dic)
# 同样在传入的字典前加上“**”,此时字典会被解析成key=value的形式。注意key值和个数不能大于形参,结果如下

# name--> 王某某
# age--> 30
# sex--> 女

 

综合一下:  

print_info("小刚",age=18,**{"sex":"男"})

#
name--> 小刚
age--> 18 
sex--> 男

  

C++解析命令行参数(仿C语言args)

C++解析命令行参数(仿C语言args)

说好不造轮子的,就管不住这手

#include <cstdio>
#include <string>
#include <vector>


bool ParseChar( const std::string& buf, std::size_t& pos, char& ch, bool& escape )
{
    char c;

    if ( pos == buf.length() )
        return false;

    // Get the character to parse
    c = buf.at( pos++ );

    if ( c == ''\\'' )
    {
        // Parse the escape character

        if ( pos != buf.length() )
        {
            // Get the character to escape
            c = buf.at( pos++ );

            if ( c == ''\\'' || c == ''"'' )
            {
                ch = c;
                escape = true;
            }
            else
            {
                // Does not support the character, just hold the ''\\'' character
                //  We need move the POS back to prepare for the character parsing
                pos--;
                ch = ''\\'';
                escape = false;
            }
        }
        else
        {
            // We can''t get the character to escape
            //  Just hold the ''\\'' character
            ch = c;
            escape = false;
        }
    }
    else
    {
        // Copy the character

        ch = c;
        escape = false;
    }

    return true;
}

bool ParseToken( const std::string& buf, std::size_t& pos, std::string& token )
{
    char c {};
    bool escape {};
    bool quote {};        // True if parsing a string
    bool doing {};        // True if parsing has started

    // Skip blank characters, if any
    while ( pos != buf.length() )
    {
        c = buf.at( pos );

        if ( c != '' '' && c != ''\t'' )
            break;

        pos++;
    }

    // Clean up the token
    token.clear();

    while ( ParseChar( buf, pos, c, escape ) )
    {
        if ( !doing )
        {
            // Parse the first character

            if ( c == ''"'' && !escape )
            {
                // Just mark the beginning of the string, don''t copy it
                quote = true;
            }
            else
            {
                // Copy the first character of the token
                token.push_back( c );
            }

            // ''\n'' is a single character token
            if ( c == ''\n'' )
                return true;

            // We have parsed any one character, the parsing has started
            doing = true;
        }
        else
        {
            if ( quote )
            {
                // Copying the character of the string here

                if ( c == ''"'' && !escape )
                {
                    // Mark the ending of a string
                    return true;
                }
                else
                {
                    // Copy the character of the string
                    token.push_back( c );
                }
            }
            else
            {
                // Copying the character of the token here

                if ( c == ''"'' && !escape )
                {
                    // We accidentally encounter a string beginning mark before the token finished
                    //  We need to finish the token and move the POS back to prepare for the string parsing
                    pos--;
                    return true;
                }

                if ( c == ''\n'' )
                {
                    // We accidentally encounter a ''\n'' before the token finished
                    //  We need to finish the token and move the POS back to prepare for the ''\n'' parsing
                    pos--;
                    return true;
                }

                if ( c == '' '' || c == ''\t'' )
                {
                    // Mark the ending of a string
                    return true;
                }
                else
                {
                    // Copy the character of the token
                    token.push_back( c );
                }
            }
        }
    }

    // If no any characters are parsed, we are at the end of the buffer
    //  returns ''false'' to finish the parsing

    return doing;
}

int main()
{
    std::string cmdline = R"(   connect
spawn  1
name "Billy Herrington"
flags          0xffff    ""
desc "boy \\next\" door"    )";

    std::size_t pos {};
    std::string token {};

    while ( ParseToken( cmdline, pos, token ) )
    {
        printf_s( "[%s]\n", token == "\n" ? "\\n" : token.c_str() );
    }

    return 0;
}

输出如下

[connect]
[\n]
[spawn]
[1]
[\n]
[name]
[Billy Herrington]
[\n]
[flags]
[0xffff]
[]
[\n]
[desc]
[boy \next" door]

我对换行符做了点特殊处理,如果不需要可以删掉相关的判断代码

 

Java Varargs 可变参数使用

Java Varargs 可变参数使用

Java1.5 提供了一个叫varargs的新功能,就是可变长度的参数。

"Varargs"是 “variable number of arguments”的意思。有时候也被简单的称为 “variable arguments”。

定义实参个数可变的方法:只要在一个形参的"类型"与"参数名"之间加上三个连续的"."(即"...",英文里的句中省略号),就可以让它和不确定个实参相匹配。

以下实例创建了 sumvarargs() 方法来统计所有数字的值。

我们在这里的 Main 方法中添加了 new int[]{10, 12, 33, 7} 4 个参数,实际上你可以在这里持续添加不同的参数,在计算 sum 的方法中都可以根据你添加的参数来进行处理。

GIT

请参考 GitHub 上的源码代码:

https://github.com/cwiki-us/java-tutorial/blob/master/src/main/java/com/ossez/lang/tutorial/usecases/VarargsCase.java

SRC

package com.ossez.lang.tutorial.usecases;  
  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
  
/\*\*  
 \* variable arguments use case \*/public class VarargsCase {  
    private static final Logger logger \= LoggerFactory.getLogger(VarargsCase.class);  
  
  /\*\*  
 \* sumVarargs \* \* @param intArrays  
  \* @return  
  \*/  
  static int sumVarargs(int... intArrays) {  
        int sum, i;  
  sum = 0;  
 for (i = 0; i < intArrays.length; i++) {  
            sum += intArrays\[i\];  
  }  
        return (sum);  
  }  
  
    /\*\*  
 \* Main Function \* \* @param args  
  \*/  
  public static void main(String args\[\]) {  
        int sum = 0;  
  sum = sumVarargs(new int\[\]{10, 12, 33, 7});  
  logger.debug("The Sum of the arrays: {}", sum);  
  }  
}

OUTPUT

程序运行的输出结果为:

2020/01/27 14:33:52 DEBUG [com.ossez.lang.tutorial.usecases.VarargsCase] - The Sum of the arrays: 62

Java Varargs 可变参数用法详解

Java Varargs 可变参数用法详解

Java1.5 提供了一个叫varargs的新功能,就是可变长度的参数。

"Varargs"是 “variable number of arguments”的意思。有时候也被简单的称为 “variable arguments”。

定义实参个数可变的方法:只要在一个形参的"类型"与"参数名"之间加上三个连续的"."(即"...",英文里的句中省略号),就可以让它和不确定个实参相匹配。

以下实例创建了 sumvarargs() 方法来统计所有数字的值。

我们在这里的 Main 方法中添加了 new int[]{10,12,33,7} 4 个参数,实际上你可以在这里持续添加不同的参数,在计算 sum 的方法中都可以根据你添加的参数来进行处理。

GIT

请参考 GitHub 上的源码代码:

https://github.com/cwiki-us/java-tutorial/blob/master/src/main/java/com/ossez/lang/tutorial/usecases/VarargsCase.java

SRC

package com.ossez.lang.tutorial.usecases;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * variable arguments use case
 */
public class VarargsCase {
  private static final Logger logger = LoggerFactory.getLogger(VarargsCase.class);

  /**
   * sumVarargs
   *
   * @param intArrays
   * @return
   */
  static int sumVarargs(int... intArrays) {
    int sum,i;
    sum = 0;
    for (i = 0; i < intArrays.length; i++) {
      sum += intArrays[i];
    }
    return (sum);
  }

  /**
   * Main Function
   *
   * @param args
   */
  public static void main(String args[]) {
    int sum = 0;
    sum = sumVarargs(new int[]{10,7});
    logger.debug("The Sum of the arrays: {}",sum);
  }
}

OUTPUT

程序运行的输出结果为:

2020/01/27 14:33:52 DEBUG [com.ossez.lang.tutorial.usecases.VarargsCase] - The Sum of the arrays: 62

扩展学习

Java 实例 - Varargs 可变参数使用

ava1.5提供了一个叫varargs的新功能,就是可变长度的参数。

"Varargs"是"variable number of arguments"的意思。有时候也被简单的称为"variable arguments"

定义实参个数可变的方法:只要在一个形参的"类型"与"参数名"之间加上三个连续的"."(即"...",英文里的句中省略号),就可以让它和不确定个实参相匹配。

以下实例创建了 sumvarargs() 方法来统计所有数字的值:

Main.java 文件

public class Main {
  static int sumvarargs(int... intArrays){
    int sum,i;
    sum=0;
    for(i=0; i< intArrays.length; i++) {
      sum += intArrays[i];
    }
    return(sum);
  }
  public static void main(String args[]){
    int sum=0;
    sum = sumvarargs(new int[]{10,33});
    System.out.println("数字相加之和为: " + sum);
  }
}

以上代码运行输出结果为:

数字相加之和为: 55

以上就是本次介绍的全部相关知识点,如果大家有任何补充内容可以联系我们小编。

今天关于没有传递参数或null时的Java 3点参数varargs行为的分享就到这里,希望大家有所收获,若想了解更多关于(十五) python3 可变长参数(arg,*args,**kwargs)、C++解析命令行参数(仿C语言args)、Java Varargs 可变参数使用、Java Varargs 可变参数用法详解等相关知识,可以在本站进行查询。

本文标签: