GVKun编程网logo

空串与NUll串(空串和null)

27

如果您想了解空串与NUll串和空串和null的知识,那么本篇文章将是您的不二之选。我们将深入剖析空串与NUll串的各个方面,并为您解答空串和null的疑在这篇文章中,我们将为您介绍空串与NUll串的相

如果您想了解空串与NUll串空串和null的知识,那么本篇文章将是您的不二之选。我们将深入剖析空串与NUll串的各个方面,并为您解答空串和null的疑在这篇文章中,我们将为您介绍空串与NUll串的相关知识,同时也会详细的解释空串和null的运用方法,并给出实际的案例分析,希望能帮助到您!

本文目录一览:

空串与NUll串(空串和null)

空串与NUll串(空串和null)

空串与NUll串

public class Note {
    public static void main(String[] args) {
        //空串是长度为0的字符串,即 ""  是一个Java对象,长度为0和内容为空
        String hello = "Hello";
        String hello2 = "";
        System.out.println(hello.length() == 0);//值是否是空串
        System.out.println(hello2.length() == 0);//值是否是空串
        hello = "Hello";
        hello2 = "";
        System.out.println(hello == null);//值是否是null
        System.out.println(hello.length() != 0 && hello != null);//值不是空串也不是null
    }
}

3-java中String值为空字符串与null的判断方法

3-java中String值为空字符串与null的判断方法

java中String值为空字符串与null的判断方法

2018年01月21日 14:53:45
阅读数:1189

Java空字符串与null的区别

1、类型

       null表示的是一个对象的值,而不是一个字符串。例如声明一个对象的引用,String a=null。 
       “”表示的是一个空字符串,也就是说它的长度为0。例如声明一个字符串String s=”“。

2、内存分配

       String a=null;表示声明一个字符串对象的引用,但指向为null,也就是说还没有指向任何的内存空间。
       String s=”“;表示声明一个字符串类型的引用,其值为“”空字符串,这个s引用指向的是空字符串的内存空间;

       在java中变量和引用变量是存在栈中(stack),而对象(new产生的)都是放在堆中(heap):

就如下: 
String str =new String(“abc”); 
       ps:=左边的是存放在栈中(stack),=右边是存放在堆中(heap)。

代码示例1:

String str1=null;
        String str2="";

        //str1==null  为true
            System.out.println("str1和null的==比较结果为:"+(str1==null)); //java.lang.NullPointerException 空指针异常 System.out.println("str1的isEmpty()方法"+(str1.isEmpty())); //java.lang.NullPointerException 空指针异常 System.out.println("str2的length()方法"+(str1.length())); //java.lang.NullPointerException 空指针异常 System.out.println("str1和null的equals比较结果为:"+(str1.equals(null))); //str2==null 为false System.out.println("str2和null的==比较结果为:"+(str2==null)); //str2=="" 为true System.out.println("str2和"+""+"的==比较结果为:"+(str2=="")); //str2.isEmpty() 为true System.out.println("str2的isEmpty()方法"+str2.isEmpty()); //str2.equals(null) 为true System.out.println("str2和null的equals方法比较结果为:"+(str2.equals(null))); //str2.isEmpty() 为true System.out.println("str2的isEmpty()方法"+(str2.isEmpty())); //str2.length() 结果为0 System.out.println("str2的length()方法"+(str2.length()));

代码示例2:

String str1 = new String() ;
        String str2 = null ;
        String str3 = "" ;
        System.out.println(str1==str2); //内存地址的比较,返回false System.out.println(str1.equals(str2)); //值的比较,返回false System.out.println(str2==str3); //内存地址的比较,返回false System.out.println(str3.equals(str2)); //值的比较,返回false System.out.println(str1==str3); //内存地址的比较,返回false System.out.println(str1.equals(str3)); //值的比较,返回true

 

通过以上的两个代码示例可以得出以下结论:

       1   如果想调用一个方法,首先要有一个对象,但是null并不是一个对象,内存中都没有它的空间,所以null是不能够调用String中的方法的,isEmpty和length和equals方法都不能够调用。 
       2   字符串对象与null的值不相等,且内存地址也不相等。 
       3   空字符串对象与null的值不相等,且内存地址也不相等。 
       4   new String()创建一个字符串对象的默认值为”” (String类型成员变量的初始值为null。

java判断字符串是都为空的方法

方法1

       最多人使用的一个方法, 直观, 方便, 但效率很低: 

if(s == null || s.equals(“”));

 

方法2

       比较字符串长度, 效率高, 是我知道的最好一个方法: 

if(s == null || s.length() == 0);

 

方法3

       Java SE 6.0 才开始提供的方法, 效率和方法二几乎相等, 但出于兼容性考虑, 推荐使用方法二. 

if(s == null || s.isEmpty());

 

方法4

       这是一种比较直观,简便的方法,而且效率也非常的高,与方法二、三的效率差不多: 

if (s == null || s == “”);

 

注意:s==null是有必要存在的。

       如果 String 类型为null, 而去进行 equals(String) 或 length() 等操作会抛出java.lang.NullPointerException。

       并且s==null 的顺序必须出现在前面,不然同样会抛出java.lang.NullPointerException。

       如以下java代码:

String s = null ;
        if(s.equals("") || s == null) { System.out.println("success"); }

运行结果如下:Exception in thread “main” java.lang.NullPointerException;会提示空指针异常。

c# – CIL – 拳击/拆箱与Nullable

c# – CIL – 拳击/拆箱与Nullable

如果我理解CLR如何处理事情和处理无效的方式,如 Boxing / Unboxing Nullable Types – Why this implementation?所述,仍然有些让我困惑的事情.例如,以下C#7代码

void C<T>(object o) where T : struct {
    if (o is T t)
        Console.WriteLine($"Argument is {typeof(T)}: {t}");
}

编译成以下CIL

IL_0000: ldarg.0
IL_0001: isinst valuetype [mscorlib]System.Nullable`1<!!T>
IL_0006: unBox.any valuetype [mscorlib]System.Nullable`1<!!T>
IL_000b: stloc.1
IL_000c: ldloca.s 1
IL_000e: call instance !0 valuetype [mscorlib]System.Nullable`1<!!T>::GetValueOrDefault()
IL_0013: stloc.0
IL_0014: ldloca.s 1
IL_0016: call instance bool valuetype [mscorlib]System.Nullable`1<!!T>::get_HasValue()
IL_001b: brfalse.s IL_003c

IL_001d: ldstr "Argument is {0}: {1}"
IL_0022: ldtoken !!T
IL_0027: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_002c: ldloc.0
IL_002d: Box !!T
IL_0032: call string [mscorlib]System.String::Format(string,object,object)
IL_0037: call void [mscorlib]System.Console::WriteLine(string)

IL_003c: ret

但是下面的C#

void D<T>(object o) where T : struct {
    if (o is T)
        Console.WriteLine($"Argument is {typeof(T)}: {(T) o}");
}

编译成以下CIL

IL_0000: ldarg.0
IL_0001: isinst !!T
IL_0006: brfalse.s IL_002c

IL_0008: ldstr "Argument is {0}: {1}"
IL_000d: ldtoken !!T
IL_0012: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0017: ldarg.0
IL_0018: unBox.any !!T
IL_001d: Box !!T
IL_0022: call string [mscorlib]System.String::Format(string,object)
IL_0027: call void [mscorlib]System.Console::WriteLine(string)

IL_002c: ret

我认为发生了什么:查看第一种方法的CIL,似乎(1)检查参数是否为[盒装?] Nullable< T>,如果是,则将其推入堆栈,否则为null,( 2)取消它(如果它为空?),(3)尝试获取其值,否则默认(T),(4)然后检查它是否有值,如果没有则分支出来.第二种方法的CIL足够简单,它只是试图取消打包参数.

如果两个代码的语义是等价的,为什么前一种情况涉及拆箱到Nullable< T>.而前一种情况“只是拆箱”?其次,在第一个CIL中,如果对象参数是一个盒装的int,我现在认为它正是它在tin上所说的(即盒装的int而不是盒装的Nullable< int>),不会isinst指令总是失败? Nullable< T>即使在CIL级别也能得到特殊待遇?

更新:在手写一些MSIL之后,看起来该对象(如果它确实是一个盒装的int)可以解包到int或Nullable< int>中.

.method private static void Foo(object o) cil managed {
    .maxstack 1
    ldarg.0
    isinst int32
    brfalse.s L_00
    ldarg.0
    unBox.any int32
    call void [mscorlib]System.Console::WriteLine(int32)
L_00:
    ldarg.0
    isinst valuetype [mscorlib]System.Nullable`1<int32>
    brfalse.s L_01
    ldarg.0
    unBox valuetype [mscorlib]System.Nullable`1<int32>
    call instance !0 valuetype [mscorlib]System.Nullable`1<int32>::GetValueOrDefault()
    call void [mscorlib]System.Console::WriteLine(int32)
L_01:
    ldarg.0
    unBox valuetype [mscorlib]System.Nullable`1<int32>
    call instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()
    brtrue.s L_02
    ldstr "No value!"
    call void [mscorlib]System.Console::WriteLine(string)
L_02:
    ret
}

解决方法

C#7中的新语法是一次进行类型检查和类型转换.在旧版本中,这通常以两种可能的方式完成.

if(o is T)
    //use (T)o
T t = o as T;
if(t != null)
    //use t

对于引用类型,第一个具有冗余转换,因为is被编译为isinst和条件分支,正如您可以从使用的CIL指令中看到的那样.第二个代码与CIL方面的第一个代码相同,减去额外的(T)o cast(编译为castclass).

对于值类型,第二个选项只能以可空类型完成,我也认为它实际上比第一个慢(必须创建一个结构).

我已经将以下方法编译为CIL:

static void C<T>(object o) where T : struct
{
    T? t = o as T?;
    if(t != null)
        Console.WriteLine("Argument is {0}: {1}",typeof(T),t);
}

生成此代码:

.method private hidebysig static void  C<valuetype .ctor ([mscorlib]System.ValueType) T>(object o) cil managed
{
  // Code size       48 (0x30)
  .maxstack  3
  .locals init (valuetype [mscorlib]System.Nullable`1<!!T> V_0)
  IL_0000:  ldarg.0
  IL_0001:  isinst     valuetype [mscorlib]System.Nullable`1<!!T>
  IL_0006:  unBox.any  valuetype [mscorlib]System.Nullable`1<!!T>
  IL_000b:  stloc.0
  IL_000c:  ldloca.s   V_0
  IL_000e:  call       instance bool valuetype [mscorlib]System.Nullable`1<!!T>::get_HasValue()
  IL_0013:  brfalse.s  IL_002f
  IL_0015:  ldstr      "Argument is {0}: {1}"
  IL_001a:  ldtoken    !!T
  IL_001f:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_0024:  ldloc.0
  IL_0025:  Box        valuetype [mscorlib]System.Nullable`1<!!T>
  IL_002a:  call       void [mscorlib]System.Console::WriteLine(string,object)
  IL_002f:  ret
}

除了调用GetValueOrDefault之外,这正是问题中的代码,因为我没有获得可空实例的实际值.

可以为空的类型不能直接装箱或取消装箱,只能通过它们的底层值,或者作为普通的空值.第一个isinst确保其他类型不会产生异常(我想isinst !! T也可以使用),而只是一个空引用.然后,unBox.any操作码从引用中形成一个可为空的实例,然后像往常一样使用它.该指令也可以写为空检查并自行构成可空实例,但这种方式更短.

C#7使用第二种方式为T t,因此如果T是值类型,则除了使用可空类型之外别无选择.为什么不选择以前的选项呢?我只能猜测它在语义或实现,变量分配等方面可能会有一些实质性的差异.因此,他们选择与新构造的实现保持一致.

为了比较,这是我在上面的方法中改变T:struct到T:class时生成的内容(以及T?到T):

.method private hidebysig static void  C<class T>(object o) cil managed
{
  // Code size       47 (0x2f)
  .maxstack  3
  .locals init (!!T V_0)
  IL_0000:  ldarg.0
  IL_0001:  isinst     !!T
  IL_0006:  unBox.any  !!T
  IL_000b:  stloc.0
  IL_000c:  ldloc.0
  IL_000d:  Box        !!T
  IL_0012:  brfalse.s  IL_002e
  IL_0014:  ldstr      "Argument is {0}: {1}"
  IL_0019:  ldtoken    !!T
  IL_001e:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_0023:  ldloc.0
  IL_0024:  Box        !!T
  IL_0029:  call       void [mscorlib]System.Console::WriteLine(string,object)
  IL_002e:  ret
}

再次与原始方法相当一致.

c# – 对于expr == null和expr!= null,与null的比较计算结果为true

c# – 对于expr == null和expr!= null,与null的比较计算结果为true

我看到一些非常奇怪的东西,我无法解释.我猜测我不熟悉的C#的一些边缘情况,还是运行时/发射器的错误?

我有以下方法:

public static bool HistoryMessageExists(DBContext context,string id)
{
    return null != context.Getobject<HistoryMessage>(id);
}

在测试我的应用程序时,我看到它是不正常的 – 它为我知道的不存在于我的数据库的对象返回true.所以我停止了在方法和立即,我跑了以下:

context.Getobject<HistoryMessage>(id)
null
null == context.Getobject<HistoryMessage>(id)
true
null != context.Getobject<HistoryMessage>(id)
true

Getobject的定义如下:

public T Getobject<T>(object pk) where T : DBObject,new()
{
    T rv = Connection.Get<T>(pk);

    if (rv != null)
    {
        rv.AttachToContext(this);
        rv.IsInserted = true;
    }

    return rv;
}

有趣的是,当将表达式转换为对象时,正确评估比较:

null == (object)context.Getobject<HistoryMessage>(id)
true
null != (object)context.Getobject<HistoryMessage>(id)
false

没有平等的运算符覆盖.

编辑:事实证明有一个操作符超载,这是不正确的.但是,为什么在内部方法通用Getobject中正确评估这个方法,在这种情况下,rv的类型为HistoryMessage.

public class HistoryMessage : EquatableIdentifiableObject
{
    public static bool HistoryMessageExists(DBContext context,string id)
    {
        var rv = context.Getobject<HistoryMessage>(id);
        bool b = rv != null;
        return b;
    }

    public static void AddHistoryMessage(DBContext context,string id)
    {
        context.InsertObject(new HistoryMessage { Id = id });
    }
}

public abstract partial class EquatableIdentifiableObject : DBObject,IObservableObject
{
    public event PropertyChangedEventHandler PropertyChanged;

    [PrimaryKey]
    public string Id { get; set; }

    //...
}

public abstract partial class EquatableIdentifiableObject
{
    //...

    public static bool operator ==(EquatableIdentifiableObject self,EquatableIdentifiableObject other)
    {
        if (ReferenceEquals(self,null))
        {
            return ReferenceEquals(other,null);
        }

        return self.Equals(other);
    }

    public static bool operator !=(EquatableIdentifiableObject self,null))
        {
            return !ReferenceEquals(other,null);
        }

        return !self.Equals(other);
    }
}

public abstract class DBObject
{
    [Ignore]
    protected DBContext Context { get; set; }

    [Ignore]
    internal bool IsInserted { get; set; }

    //...
}

这里发生了什么?

解决方法

>如你已经澄清的那样,==操作符失败,因为您的重载不正确.
>当转换为对象时,==操作符正常工作,因为它是被使用的对象的==的实现,而不是EquatableIdentifiableObject.
>在方法Getobject中,操作符正确地求值,因为它不是EquatableIdentifiableObject的正在使用的==的实现.在C#泛型中,运行时解析(至少在这里是相关的),而不是在编译时解决.注意==是静态而不是虚拟的.所以类型T在运行时被解析,但是调用==必须在编译时解决.在编译时,当编译器解析==它不会知道使用EquatableIdentifiableObject的==的实现.因为类型T有这个约束:其中T:DBObject,new(),DBObject的实现(如果有的话)将被使用.如果DBObject没有定义==,那么将使用第一个基类的实现(直到对象).

有关EquatableIdentifiableObject的实现的更多评论==:

>您可以替换此部分:

if (ReferenceEquals(self,null))
{
     return ReferenceEquals(other,null);
}

有:

// If both are null,or both are the same instance,return true.
if (object.ReferenceEquals(h1,h2))
{
    return true;
}

>更换更有力

public static bool operator !=(EquatableIdentifiableObject self,EquatableIdentifiableObject other)
{
    ...
}

有:

public static bool operator !=(EquatableIdentifiableObject self,EquatableIdentifiableObject other)
{
    return !(self == other);
}

>为==定义签名的方法略有误导.第一个参数命名为self,第二个命名为other.如果==是一个实例方法就可以了.由于它是一种静态方法,所以名字自身有点误导.更好的名称将是o1和o2或沿着这条线的东西,以便两个操作数在更平等的基础上对待.

DBNull与Null的区别

DBNull与Null的区别

Null是.net中无效的对象引用。

dbnull是一个类。dbnull.Value是它唯一的实例。它指数据库中数据为空(<NULL>)时,在.net中的值。

null表示一个对象的指向无效,即该对象为空对象

dbnull.Value表示一个对象在数据库中的值为空,或者说未初始化,dbnull.Value对象是指向有效的对象。 

dbnull在DotNet是单独的一个类型 System.dbnull 。它只有一个值 dbnull.Value 。dbnull 直接继承 Object ,所以 dbnull 不是 string,不是 int,也不是 DateTime 。。。

但是为什么 dbnull 可以表示数据库中的字符串,数字,或日期呢?原因是DotNet储存这些数据的类(DaTarow等)都是以 object 的形式来储存数据的。

对于 DaTarow,它的 row[column] 返回的值永远不为 null , 要么就是具体的为column 的类型的值 。要么就是 dbnull 。 所以 row[column].ToString() 这个写法永远不会在ToString那里发生NullReferenceException,但有可能抛下标越界的异常。

dbnull 实现了 IConvertible 。 但是,除了 ToString 是正常的外,其他的ToXXX都会抛出不能转换的错误。

在 IDbCommand(OleDbCommand,sqlCommand...) 的ExecuteScalar的返回值中,情况可以这样分析:

select 1 这样返回的object是 1
select null 这样返回的是dbnull.Value
select isnull(null,1) 返回的是 1
select top 0 id from table1 这样返回的值是null
select isnull(id,0) from table1 where 1=0 返回的值是null

这里 ExecuteScalar 的规则就是,返回第一列,第一行的数据。如果一行都没有,那么ExecuteScalar就返回null。如果有第一行,但是第一列为空,那么返回的是 dbnull 。如果第一列第一行不为空,那么ExecuteScalar就直接对应的DotNet的值。

规则就是这样的。这里容易犯的一个错误是,把ExecuteScalar返回dbnull与null的情况混淆,例如:

string username=cmd.ExecuteScalar().ToString();

除非你认为cmd执行后,肯定至少有一行数据,否则这里就会出错。

又或者 select id from usertable where username=@name 这样的sql语句,如果找不到记录,那么ExecuteScalar则会返回null,所以千万不要

int userid=Convert.ToInt32(cmd.ExecuteScalar());

或者你会这样写 sql 语句:select isnull(id,0) from usertable where username=@name

但是 int userid=Convert.ToInt32(cmd.ExecuteScalar()); 依然会出错,因为上面的语句不成立时,仍然是不返回任何行。

对于IDbDataParameter(OleDDbParameter,sqlParameter..)的Value,如果为null,则代表该参数没有指定,或者是代表DEFAULT。如果为dbnull.Value,则代表sql中的NULL

所以,如果你要调用存储过程,里面有默认参数 @val nvarchar(20)="AABB", 
那么cmd.Parameters["@val"].Value=null 代表使用这个默认的 "AABB"
而cmd.Parameters["@val"].Value=dbnull.Value 代表使用NULL来传给 @val

你可以用Convert.Isdbnull来判断一个值是否dbnull。注意Convert.Isdbnull(null)是false,也就是说null跟dbnull.Value是不等的。

关于空串与NUll串空串和null的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于3-java中String值为空字符串与null的判断方法、c# – CIL – 拳击/拆箱与Nullable、c# – 对于expr == null和expr!= null,与null的比较计算结果为true、DBNull与Null的区别等相关内容,可以在本站寻找。

本文标签: