精华内容
下载资源
问答
  • Java中null是一个关键字,用来标识一个不确定的对象。因此可以将null赋给引用类型变量,但不可以将null赋给基本类型变量。 比如:int a = null;是错误的。Ojbect o = null是正确的。 Java中,变量的适用都遵循...

    一、null是代表不确定的对象

           Java中,null是一个关键字,用来标识一个不确定的对象。因此可以将null赋给引用类型变量,但不可以将null赋给基本类型变量。

    比如:int a = null;是错误的。Ojbect o = null是正确的。

    Java中,变量的适用都遵循一个原则,先定义,并且初始化后,才可以使用。我们不能在int a后,不给a赋值,就去打印a的值。这条对对于引用类型变量也是适用的。

          有时候,我们定义一个引用类型变量,在刚开始的时候,无法给出一个确定的值,但是不指定值,程序可能会在try语句块中初始化值。这时候,我们下面使用变量的时候就会报错。这时候,可以先给变量指定一个null值,问题就解决了。例如:

    Connection conn = null;
    
    try {
    
    conn = DriverManager.getConnection("url", "user", "password");
    
    } catch (SQLException e) {
    
    e.printStackTrace();
    
    }
    
    String catalog = conn.getCatalog();
    
    如果刚开始的时候不指定conn = null,则最后一句就会报错。

     

    二、null本身不是对象,也不是Objcet的实例

            null本身虽然能代表一个不确定的对象,但就null本身来说,它不是对象,也不知道什么类型,也不是java.lang.Object的实例。

    可以做一个简单的例子:

          null是对象吗? 属于Object类型吗?

    if (null instanceof java.lang.Object) {
    
    System.out.println("null属于java.lang.Object类型");
    
    } else {
    
    System.out.println("null不属于java.lang.Object类型");
    
    }

    输出结果为:null不属于java.lang.Object类型

    三、Java默认给变量赋值

             在定义变量的时候,如果定义后没有给变量赋值,则Java在运行时会自动给变量赋值。赋值原则是整数类型int、byte、short、long的自动赋值为0,带小数点的float、double自动赋值为0.0,boolean的自动赋值为false,其他各供引用类型变量自动赋值为null。

    四、容器类型与null (重点)

    • List:允许重复元素,可以加入任意多个null。
    • Set:不允许重复元素,最多可以加入一个null。
    • Map:Map的key最多可以加入一个null,value字段没有限制。
    • 数组:基本类型数组,定义后,如果不给定初始值,则java运行时会自动给定值。引用类型数组,不给定初始值,则所有的元素值为null。

    五、null的其他作用

    1、判断一个引用类型数据是否null。 用==来判断

    2、释放内存,让一个非null的引用类型变量指向null。这样这个对象就不再被任何对象应用了。等待JVM垃圾回收机制去回收。

    展开全文
  • java中set用法

    千次阅读 2017-06-05 07:54:50
    在Java中使用Set,可以方便地将需要的类型以集合类型保存在一个变量中.主要应用在显示列表.Set是一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个...

    Java中使用Set,可以方便地将需要的类型以集合类型保存在一个变量中.主要应用在显示列表.Set是一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学上的 set 抽象。

    以下是在JAVA中使用Set的范例,希望对大家有帮助.

    import java.util.*;
    public class test {

     /**
      * @param args
      */
     public static void main(String[] args) {
      // TODO Auto-generated method stub
       Set  set=new HashSet();
       set.add("abc");
       set.add("cde");
       set.add("efg");
       set.add("fgh");    
       set.add("abc"); //重复的abc,set会自动将其去掉   
       System.out.println("size="+ set.size() );
        List list = new ArrayList();
        list.add("abc");
        list.add("aaa");
        list.add("fff");
        set.addAll(list); //将list中的值加入set,并去掉重复的abc
             System.out.println("size="+ set.size() );
            for( Iterator   it = set.iterator();  it.hasNext(); )
            {             
                System.out.println("value="+it.next().toString());            
            } 
     }   

    }

     

    ***************************************************************

    对JAVA的集合的理解是想对于数组
        数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型)
        JAVA集合可以存储和操作数目不固定的一组数据。
        所有的JAVA集合都位于 java.util包中!
        JAVA集合只能存放引用类型的的数据,不能存放基本数据类型.
        JAVA集合主要分为三种类型:
        Set(集)
        List(列表)
        Map(映射)
        Collection 接口
        Collection是最基本的集合接口,声明了适用于JAVA集合(只包括Set和List)的通用方法。
        Set 和List 都继承了Conllection,Map没有
        Collection接口的方法:
        boolean add(Object o)   :向集合中加入一个对象的引用
        void clear()                        :删除集合中所有的对象,即不再持有这些对象的引用
        boolean isEmpty()           :判断集合是否为空
        boolean contains(Object o): 判断集合中是否持有特定对象的引用
        Iterartor iterator()              : 返回一个Iterator对象,可以用来遍历集合中的元素
        boolean remove(Object o):从集合中删除一个对象的引用
        int size()                               :返回集合中元素的数目
        Object[] toArray()                 :返回一个数组,该数组中包括集合中的所有元素
        关于:Iterator() 和toArray() 方法都用于集合的所有的元素,前者返回一个Iterator对象,后者返回一个包含集合中所有元素的数组。
        Iterator接口声明了如下方法:
        hasNext(): 判断集合中元素是否遍历完毕,如果没有,就返回true
        next()       :返回下一个元素
        remove():从集合中删除上一个有next()方法返回的元素。
        Set(集合):
        Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。
        Set接口主要实现了两个实现类:
        HashSet : HashSet类按照哈希算法来存取集合中的对象,存取速度比较快
        TreeSet   : TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序。
        Set 的用法:
        存放的是对象的引用,没有重复对象
        Set set=new HashSet();
        String s1=new String("hello");
        String s2=s1;
        String s3=new String("world");
        set.add(s1);
        set.add(s2);
        set.add(s3);
        System.out.println(set.size());//打印集合中对象的数目 为 2。
        Set 的 add()方法是如何判断对象是否已经存放在集合中?
        boolean isExists=false;
        Iterator iterator=set.iterator();
        while(it.hasNext())           {
        String oldStr=it.next();
        if(newStr.equals(oldStr)){
        isExists=true;
        }
        }

     

    List(列表):
        List的特征是其元素以线性方式存储,集合中可以存放重复对象。
        List接口主要实现类包括:
        ArrayList() : 代表长度可以改变得数组。可以对元素进行随机的访问,向ArrayList()中插入与
        与删除元素的速度慢。
        LinkedList(): 在实现中采用链表数据结构。插入和删除速度快,访问速度慢。
        对于List的随机访问来说,就是只随机来检索位于特定位置的元素。
        List 的 get(int index) 方法放回集合中由参数index指定的索引位置的对象,下标从“0” 开始。
        最基本的两种检索集合中的所有对象的方法:
        1: 用for循环和get()方法:
        for(int i=0; i<list.size();i++){
        System.out.println(list.get(i));
        }
        2: 使用 迭代器(Iterator):
        Iterator it=list.iterator();
        while(it.hashNext){
        System.out.println(it.next);
        }
        Map(映射):
        Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。
        Map没有继承于Collection接口
        从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
        Map 的常用方法:
        1 添加,删除操作:
        Object put(Object key, Object value): 向集合中加入元素
        Object remove(Object key):   删除与KEY相关的元素
        void putAll(Map t):   将来自特定映像的所有元素添加给该映像
        void clear(): 从映像中删除所有映射
        2 查询操作:
        Object get(Object key): 获得与关键字key相关的值
        Map集合中的键对象不允许重复,也就说,任意两个键对象通过equals()方法比较的结果都是false.
        但是可以将任意多个键独享映射到同一个值对象上。
        Conllections : 集合实用类
        Conllections提供了供JAVA集合实用的静态方法
        总结:
        JAVA集合的基本用法,都归纳了,上面这些是平常最常用的JAVA集合,具体的其他的,还要参考JDK帮助文档了,呵呵 关于 Map的应用,还有很多,具体就是这个,Conllections提供了很多 List /Map 实用的方法,对平常开发非常有用。

     

     

    boolean containsKey(Object key): 判断映像中是否存在关键字key
        boolean containsValue(Object value): 判断映像中是否存在值value
        int size(): 返回当前映像中映射的数量
        boolean isEmpty() :判断映像中是否有任何映射
        本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wordinput/archive/2010/01/22/5223876.aspx
        List按对象进入的顺序保存对象,不做排序或编辑操作。Set对每个对象只接受一次,并使用自己内部的排序方法(通常,你只关心某个元素是否属于Set,而不关心它的顺序--否则应该使用List)。Map同样对每个元素保存一份,但这是基于"键"的,Map也有内置的排序,因而不关心元素添加的顺序。如果添加元素的顺序对你很重要,应该使用 LinkedHashSet或者LinkedHashMap.
        List的功能方法
        实际上有两种List: 一种是基本的ArrayList,其优点在于随机访问元素,另一种是更强大的LinkedList,它并不是为快速随机访问设计的,而是具有一套更通用的方法。
        List : 次序是List最重要的特点:它保证维护元素特定的顺序。List为Collection添加了许多方法,使得能够向List中间插入与移除元素(这只推荐LinkedList使用。)一个List可以生成ListIterator,使用它可以从两个方向遍历List,也可以从List中间插入和移除元素。
        ArrayList : 由数组实现的List。允许对元素进行快速随机访问,但是向List中间插入与移除元素的速度很慢。ListIterator只应该用来由后向前遍历ArrayList,而不是用来插入和移除元素。因为那比LinkedList开销要大很多。
        LinkedList : 对顺序访问进行了优化,向List中间插入与删除的开销并不大。随机访问则相对较慢。(使用ArrayList代替。)还具有下列方法:addFirst(), addLast(), getFirst(), getLast(), removeFirst() 和 removeLast(), 这些方法 (没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。
        Set的功能方法
        Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面有两个不同的List。实际上Set就是Collection,只是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)Set不保存重复的元素(至于如何判断元素相同则较为负责)
        Set : 存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。加入Set的元素必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。
        HashSet : 为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。
        TreeSet : 保存次序的Set, 底层为树结构。使用它可以从Set中提取有序的序列。
        LinkedHashSet : 具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。
        Map的功能方法
        方法put(Object key, Object value)添加一个“值”(想要得东西)和与“值”相关联的“键”(key)(使用它来查找)。方法get(Object key)返回与给定“键”相关联的“值”。可以用containsKey()和containsValue()测试Map中是否包含某个“键”或“值”。标准的Java类库中包含了几种不同的Map:HashMap, TreeMap, LinkedHashMap, WeakHashMap, IdentityHashMap。它们都有同样的基本接口Map,但是行为、效率、排序策略、保存对象的生命周期和判定“键”等价的策略等各不相同。
        执行效率是Map的一个大问题。看看get()要做哪些事,就会明白为什么在ArrayList中搜索“键”是相当慢的。而这正是HashMap提高速度的地方。HashMap使用了特殊的值,称为“散列码”(hash code),来取代对键的缓慢搜索。“散列码”是“相对唯一”用以代表对象的int值,它是通过将该对象的某些信息进行转换而生成的。所有Java对象都能产生散列码,因为hashCode()是定义在基类Object中的方法。
        HashMap就是使用对象的hashCode()进行快速查询的。此方法能够显着提高性能。
        Map : 维护“键值对”的关联性,使你可以通过“键”查找“值”
        HashMap : Map基于散列表的实现。插入和查询“键值对”的开销是固定的。可以通过构造器设置容量capacity和负载因子load factor,以调整容器的性能。
        LinkedHashMap : 类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点。而在迭代访问时发而更快,因为它使用链表维护内部次序。
        TreeMap : 基于红黑树数据结构的实现。查看“键”或“键值对”时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在于,你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。
        WeakHashMao : 弱键(weak key)Map,Map中使用的对象也被允许释放: 这是为解决特殊问题设计的。如果没有map之外的引用指向某个“键”,则此“键”可以被垃圾收集器回收。
        IdentifyHashMap : 使用==代替equals()对“键”作比较的hash map。专为解决特殊问题而设计。

    展开全文
  • 我们开发经常碰到的NullPointerException.假设我们有两个类,他们的UML类图如下图所示 这种情况下,有如下代码 user.getAddress().getProvince(); 这种写法,user为null时,是有可能报...

    我们在开发中经常碰到的NullPointerException.假设我们有两个类,他们的UML类图如下图所示

    o_optional1.png

    在这种情况下,有如下代码

    user.getAddress().getProvince();

    这种写法,在user为null时,是有可能报NullPointerException异常的。为了解决这个问题,于是采用下面的写法

    if(user!=null){
        Address address = user.getAddress();
        if(address!=null){
            String province = address.getProvince();
        }
    }

    Java8以后这种写法是比较繁琐的,JAVA8提供了Optional类来优化这种写法,接下来介绍。

    API介绍

    先介绍一下API,同时结合源码。一个个API罗列出来,找到重点。

    1、Optional(T value),empty(),of(T value),ofNullable(T value)。这四个函数之间具有相关性,因此放在一组进行记忆。

    Optional(T value),构造函数,它是private权限的,不能由外部调用的。其余三个函数是public权限。Optional的本质,就是内部储存了一个真实的值,在构造的时候,就直接判断其值是否为空。先看下Optional(T value)构造函数的源码,如下图所示

    o_optional2png.png

    of(T value)的源码如下

    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

    也就是说of(T value)函数内部调用了构造函数。根据构造函数的源码我们可以得出两个结论:

    • 通过of(T value)函数所构造出的Optional对象,当Value值为空时,依然会报NullPointerException。

    • 通过of(T value)函数所构造出的Optional对象,当Value值不为空时,能正常构造Optional对象。

    除此之外呢,Optional类内部还维护一个value为null的对象,大概就是长下面这样的

    public final class Optional<T> {
        //省略....
        private static final Optional<?> EMPTY = new Optional<>();
        private Optional() {
            this.value = null;
        }
        //省略...
        public static<T> Optional<T> empty() {
            @SuppressWarnings("unchecked")
            Optional<T> t = (Optional<T>) EMPTY;
            return t;
        }
    }

    那么,empty()的作用就是返回EMPTY对象。

    所以先看一下ofNullable(T value)的作用,上源码

     public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

    三目运算应该可以看的懂。相比较of(T value)的区别就是,当value值为null时,of(T value)会报NullPointerException异常;ofNullable(T value)不会throw Exception,ofNullable(T value)直接返回一个EMPTY对象。

    那是不是意味着,我们在项目中只用ofNullable函数而不用of函数呢?

    不是的,一个东西存在那么自然有存在的价值。当我们在运行过程中,不想隐藏NullPointerException。而是要立即报告,这种情况下就用Of函数。但是不得不承认,这样的场景真的很少。

    2、orElse(T other),orElseGet(Supplier<? extends T> other)和orElseThrow(Supplier<? extends X> exceptionSupplier)

    这三个函数放一组进行记忆,都是在构造函数传入的value值为null时,进行调用的。orElseorElseGet的用法如下所示,相当于value值为null时,给予一个默认值:

    
    public void test() {
        User user = null;
        user = Optional.ofNullable(user).orElse(createUser());
        user = Optional.ofNullable(user).orElseGet(() -> createUser());
        
    }
    public User createUser(){
        User user = new User();
        user.setName("zhangsan");
        return user;
    }

    这两个函数的区别:

    当user值不为null时,orElse函数依然会执行createUser()方法,而orElseGet函数并不会执行createUser()方法。

    至于orElseThrow,就是value值为null时,直接抛一个异常出去,用法如下所示

    User user = null;
    Optional.ofNullable(user).orElseThrow(()->new Exception("用户不存在"));

    3、map(Function<? super T, ? extends U> mapper)和flatMap(Function<? super T, Optional<U>> mapper)

    这两个函数放在一组,这两个函数主要是转换值。

    直接上源码

     public final class Optional<T> {
        //省略....
         public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
            Objects.requireNonNull(mapper);
            if (!isPresent())
                return empty();
            else {
                return Optional.ofNullable(mapper.apply(value));
            }
        }
        //省略...
         public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
            Objects.requireNonNull(mapper);
            if (!isPresent())
                return empty();
            else {
                return Objects.requireNonNull(mapper.apply(value));
            }
        }
    }

    这两个函数,在函数体上没什么区别。唯一区别的就是入参,map函数所接受的入参类型为Function<? super T, ? extends U>,而flapMap的入参类型为Function<? super T, Optional<U>>

    在具体用法上,对于map:

    如果User结构是下面这样的

    public class User {
        private String name;
        public String getName() {
            return name;
        }
    }

    这时候取name的写法如下所示

    String city = Optional.ofNullable(user).map(u-> u.getName()).get();

    对于flatMap:

    如果User结构是下面这样的

    public class User {
        private String name;
        public Optional<String> getName() {
            return Optional.ofNullable(name);
        }
    }

    这时候取name的写法如下:

    String city = Optional.ofNullable(user).flatMap(u-> u.getName()).get();

    4、isPresent()和ifPresent(Consumer<? super T> consumer)

    isPresent即判断value值是否为空,而ifPresent就是在value值不为空时,做一些操作。这两源码如下

    public final class Optional<T> {
        //省略....
        public boolean isPresent() {
            return value != null;
        }
        //省略...
        public void ifPresent(Consumer<? super T> consumer) {
            if (value != null)
                consumer.accept(value);
        }
    }

    需要注意的是,不要把

    if (user != null){
       // TODO: do something
    }

    写成

    User user = Optional.ofNullable(user);
    if (Optional.isPresent()){
       // TODO: do something
    }

    这样写,其实没啥区别。

    至于ifPresent(Consumer<? super T> consumer),用法也很简单,如下所示

    Optional.ofNullable(user).ifPresent(u->{
        // TODO: do something
    });

    5、filter(Predicate<? super T> predicate),源码

    public final class Optional<T> {
        //省略....
       Objects.requireNonNull(predicate);
            if (!isPresent())
                return this;
            else
                return predicate.test(value) ? this : empty();
    }

    filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty

    用法如下:

    Optional<User> user1 = Optional.ofNullable(user).filter(u -> u.getName().length()<6);

    如果user的name的长度是小于6的,则返回。如果是大于6的,则返回一个EMPTY对象。

    实战

    例一

    在函数方法中,以前写法

    public String getCity(User user)  throws Exception{
            if(user!=null){
                if(user.getAddress()!=null){
                    Address address = user.getAddress();
                    if(address.getCity()!=null){
                        return address.getCity();
                    }
                }
            }
            throw new Excpetion("取值错误"); 
        }

    JAVA8写法

    public String getCity(User user) throws Exception{
        return Optional.ofNullable(user)
                       .map(u-> u.getAddress())
                       .map(a->a.getCity())
                       .orElseThrow(()->new Exception("取值错误"));
    }

    例二

    在主程序中,以前写法

    if(user!=null){
        dosomething(user);
    }

    JAVA8写法

     Optional.ofNullable(user)
        .ifPresent(u->{
            dosomething(u);
    });

    例三

    以前写法

    public User getUser(User user) throws Exception{
        if(user!=null){
            String name = user.getName();
            if("zhangsan".equals(name)){
                return user;
            }
        }else{
            user = new User();
            user.setName("zhangsan");
            return user;
        }
    }

    java8写法

    public User getUser(User user) {
        return Optional.ofNullable(user)
                       .filter(u->"zhangsan".equals(u.getName()))
                       .orElseGet(()-> {
                            User user1 = new User();
                            user1.setName("zhangsan");
                            return user1;
                       });
    }

    采用这种链式编程,虽然代码简洁了。但是,逻辑不明显,只有熟悉了API怎么用,可以很快了解逻辑,实际应用中自己看着来。

    展开全文
  • Null 貌似哪里都是个头疼的问题,比如 Java 里让人头疼的 NullPointerException,为了避免猝不及防的空指针异常,程序猿们不得不代码里小心翼翼的各种 if 判断,麻烦而又臃肿,为此 java8 引入了 Optional 来...

    Null 貌似在哪里都是个头疼的问题,比如 Java 里让人头疼的 NullPointerException,为了避免猝不及防的空指针异常,程序猿们不得不在代码里小心翼翼的各种 if 判断,麻烦而又臃肿,为此 java8 引入了 Optional 来避免这一问题。


    下面咱们要聊的是 MySQL 里的 null,在大量的 MySQL 优化文章和书籍里都提到了字段尽可能用NOT NULL,而不是NULL,除非特殊情况。但却都只给结论不说明原因,犹如鸡汤不给勺子一样,让不少初学者对这个结论半信半疑或者云里雾里。本文今天就详细的剖析下使用 Null 的原因,并给出一些不用 Null 的理由。


    1、NULL 为什么这么多人用?


    • NULL是创建数据表时默认的,初级或不知情的或怕麻烦的程序员不会注意这点。

    • 很多人员都以为not null 需要更多空间,其实这不是重点。

    • 重点是很多程序员觉得NULL在开发中不用去判断插入数据,写sql语句的时候更方便快捷。


    2、是不是以讹传讹?


    MySQL 官网文档:


    NULL columns require additional space in the rowto record whether their values are NULL. For MyISAM tables, each NULL columntakes one bit extra, rounded up to the nearest byte.


    Mysql难以优化引用可空列查询,它会使索引、索引统计和值更加复杂。可空列需要更多的存储空间,还需要mysql内部进行特殊处理。可空列被索引后,每条记录都需要一个额外的字节,还能导致MYisam 中固定大小的索引变成可变大小的索引。


    —— 出自《高性能mysql第二版》


    照此分析,还真不是以讹传讹,这是有理论依据和出处的。


    3、给我一个不用 Null 的理由?


    (1)所有使用NULL值的情况,都可以通过一个有意义的值的表示,这样有利于代码的可读性和可维护性,并能从约束上增强业务数据的规范性。

    (2)NULL值到非NULL的更新无法做到原地更新,更容易发生索引分裂,从而影响性能。


    注意:但把NULL列改为NOT NULL带来的性能提示很小,除非确定它带来了问题,否则不要把它当成优先的优化措施,最重要的是使用的列的类型的适当性。


    (3)NULL值在timestamp类型下容易出问题,特别是没有启用参数explicit_defaults_for_timestamp

    (4)NOT IN、!= 等负向条件查询在有 NULL 值的情况下返回永远为空结果,查询容易出错


    create table table_2 (

         `id` INT (11) NOT NULL,

        user_name varchar(20) NOT NULL

    )

     

     

    create table table_3 (

         `id` INT (11) NOT NULL,

        user_name varchar(20)

    )

     

    insert into table_2 values (4,"zhaoliu_2_1"),(2,"lisi_2_1"),(3,"wangmazi_2_1"),(1,"zhangsan_2"),(2,"lisi_2_2"),(4,"zhaoliu_2_2"),(3,"wangmazi_2_2")

     

    insert into table_3 values (1,"zhaoliu_2_1"),(2, null)

     

    -- 1、NOT IN子查询在有NULL值的情况下返回永远为空结果,查询容易出错

    select user_name from table_2 where user_name not in (select user_name from table_3 where id!=1)

     

    mysql root@10.48.186.32:t_test_zz5431> select user_name from table_2 where user_name not

                                        -> in (select user_name from table_3 where id!=1);

    +-------------+

    | user_name   |

    |-------------|

    +-------------+

    0 rows in set

    Time: 0.008s

    mysql root@10.48.186.32:t_test_zz5431>

     

    -- 2、单列索引不存null值,复合索引不存全为null的值,如果列允许为null,可能会得到“不符合预期”的结果集

    -- 如果name允许为null,索引不存储null值,结果集中不会包含这些记录。所以,请使用not null约束以及默认值。

    select * from table_3 where name != 'zhaoliu_2_1'

     

    -- 3、如果在两个字段进行拼接:比如题号+分数,首先要各字段进行非null判断,否则只要任意一个字段为空都会造成拼接的结果为null。

    select CONCAT("1",null) from dual; -- 执行结果为null。

     

    -- 4、如果有 Null column 存在的情况下,count(Null column)需要格外注意,null 值不会参与统计。

    mysql root@10.48.186.32:t_test_zz5431> select * from table_3;

    +------+-------------+

    |   id | user_name   |

    |------+-------------|

    |    1 | zhaoliu_2_1 |

    |    2 | <null>      |

    |   21 | zhaoliu_2_1 |

    |   22 | <null>      |

    +------+-------------+

    4 rows in set

    Time: 0.007s

    mysql root@10.48.186.32:t_test_zz5431> select count(user_name) from table_3;

    +--------------------+

    |   count(user_name) |

    |--------------------|

    |                  2 |

    +--------------------+

    1 row in set

    Time: 0.007s

     

    -- 5、注意 Null 字段的判断方式, = null 将会得到错误的结果。

    mysql root@localhost:cygwin> create index IDX_test on table_3 (user_name);

    Query OK, 0 rows affected

    Time: 0.040s

    mysql root@localhost:cygwin>  select * from table_3 where user_name is nullG

    ***************************[ 1. row ]***************************

    id        | 2

    user_name | None

     

    1 row in set

    Time: 0.002s

    mysql root@localhost:cygwin> select * from table_3 where user_name = nullG

     

    0 rows in set

    Time: 0.002s

    mysql root@localhost:cygwin> desc select * from table_3 where user_name = 'zhaoliu_2_1'G

    ***************************[ 1. row ]***************************

    id            | 1

    select_type   | SIMPLE

    table         | table_3

    type          | ref

    possible_keys | IDX_test

    key           | IDX_test

    key_len       | 23

    ref           | const

    rows          | 1

    Extra         | Using where

     

    1 row in set

    Time: 0.006s

    mysql root@localhost:cygwin> desc select * from table_3 where user_name = nullG

    ***************************[ 1. row ]***************************

    id            | 1

    select_type   | SIMPLE

    table         | None

    type          | None

    possible_keys | None

    key           | None

    key_len       | None

    ref           | None

    rows          | None

    Extra         | Impossible WHERE noticed after reading const tables

     

    1 row in set

    Time: 0.002s

    mysql root@localhost:cygwin> desc select * from table_3 where user_name is nullG

    ***************************[ 1. row ]***************************

    id            | 1

    select_type   | SIMPLE

    table         | table_3

    type          | ref

    possible_keys | IDX_test

    key           | IDX_test

    key_len       | 23

    ref           | const

    rows          | 1

    Extra         | Using where

     

    1 row in set

    Time: 0.002s

    mysql root@localhost:cygwin>


    (5)Null 列需要更多的存储空间:需要一个额外字节作为判断是否为 NULL 的标志位


    alter table table_3 add index idx_user_name (user_name);

    alter table table_2 add index idx_user_name (user_name);

    explain select * from table_2 where user_name='zhaoliu_2_1';

    explain select * from table_3 where user_name='zhaoliu_2_1';




    可以看到同样的 varchar(20) 长度,table_2 要比 table_3 索引长度大,这是因为:


    两张表的字符集不一样,且字段一个为 NULL 一个非 NULL。




    key_len 的计算规则和三个因素有关:数据类型、字符编码、是否为 NULL


    key_len 62 == 20*3(utf8 3字节) + 2 (存储 varchar 变长字符长度 2字节,定长字段无需额外的字节)


    key_len 83 == 20*4(utf8mb4 4字节) + 1 (是否为 Null 的标识) + 2 (存储 varchar 变长字符长度 2字节,定长字段无需额外的字节)


    所以说索引字段最好不要为NULL,因为NULL会使索引、索引统计和值更加复杂,并且需要额外一个字节的存储空间。基于以上这些理由和原因,我想咱们不用 Null 的理由应该是够了。


    转载链接:my.oschina.net/leejun2005/blog/1342985

    展开全文
  • NULL 博文链接:https://icgemu.iteye.com/blog/467848
  • 浅谈Java中try catch 的用法

    万次阅读 多人点赞 2018-11-10 15:37:21
    Java提供了一个“捕获”异常的的处理器(处理器)对异常情况进行处理。 如果没有提供处理器机制,程序就会终止,并控制台上打印一条信息,给出异常的类型.L 比如:使用了NULL引用或者是数组越界等。 异常有两...
  • 网上下了一个,但我就是不知道怎么数据库体现 <%@ page language="java" contentType="text/...结果是null,这个方面我不懂,另外,如果说eWebEditor这个框架里面上传图片的话,struts2又怎么体现
  • 对于synchronized,基本理解就是可以把任何一个非null对象作为”锁”。1、作用方法上时,锁住的便是对象实例(this)public class SynchronizedObject { /* * 当synchronized作用方法上时,锁住的便是对象实例...
  • Java中Set的用法

    2019-10-02 19:20:36
    在Java中使用Set,可以方便地将需要的类型,以集合类型保存在一个变量中.主要应用在显示列表. Set是一个不包含重复元素的collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一...
  • java中集合中工具用法

    2017-03-24 09:50:26
    1: Arrays static T[] ...复制指定的数组,截取或用 null 填充(如有必要),以使副本具有指定的长度。...对于副本有效而在原数组无效的所有索引,副本将包含 null。当且仅
  • Java中的Set用法

    2017-04-25 16:53:55
    在Java中使用Set,可以方便地将需要的类型以集合类型保存在一个变量中.主要应用在显示列表.Set是一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个...
  • java中有 instanceof 关键字,actionscript 3 中它也是一个关键字,用法java中一样 as 比较左边的值是不是右边的的类型 ,如果是,则返回object如果 不是,则返回null is 是取代instanceof的一个新关键字,...
  • Java中StringBuffer的用法详解

    万次阅读 多人点赞 2017-02-22 00:42:14
    Java中StringBuffer的用法详解众所周知String作为不可修改的对象,即每次更改String都会产生一个新的字符串对象,与之相对应的StringBuffer类的对象能够进行多次修改并且不会产生新的未使用的对象,因此内存上要...
  • 在JAVA与C++ 空字符写法不同 C++ ----------------------------------NULL java ----------------------------------null 在数据链表的使用通常使用dummyHead dummyHead是自己单独定义的一个头结点,返回他的next...
  • 但是 JavaScript 却同时存在undefined和null,这主要是由于历史原因,感兴趣的可以查一下。 二者的主要用法区别如下: undefined 变量被声明了,但没有赋值时,就等于undefined 调用函数时,应该提供的...
  • java中null与空值

    千次阅读 2008-05-25 22:55:00
    在java里,如何理解null与空值,很多人在入手时都会犯下错误,关于这个问题,我就不多说了,有网友已经整理出来了。出处:http://hi.baidu.com/origin100/blog/item/7f4b72edf0eee54b79f0555b.html null或空值的判断...
  • 关于java中链表的用法

    2008-12-05 13:08:54
     /*当前结点前插入一个结点,并使其成为当前结点*/  {  Node e=new Node(d);  if(Length==0)  {  Tail=e;  Head=e;  }  else  {  Node temp=cursor();  e.next=temp;  if(Pointer==null)...
  • <一>. this的用法 构造方法是创建java对象的重要途径,通过new关键字调用构造器时,构造器返回该类的对象,但是这个对手并不是完全由... 因此,构造方法也可以使用this代表“当前对象”. 书上对于this的描述 this
  • 静态方法不能访问非静态成员方法和非静态成员变量,但是非静态成员方法是可以访问静态成员方法/变量的。 static方法 可以没有创建任何对象的前提下,仅仅通过类本身来调用static方法。 例如 下面是一个...
  • java Console的用法

    万次阅读 2017-08-20 18:35:50
    Java.io.Console 只能用标准输入、输出流未被重定向的原始控制台使用, Eclipse 或者其他 IDE 的控制台是用不了的。 Console console=System.console(); if(console!=null) { System.out.println("input ...
  • java中Set类接口的用法

    2017-06-01 15:16:00
    在Java中使用Set,可以方便地将需要的类型,以集合类型保存在一个变量中.主要应用在显示列表. Set是一个不包含重复元素的collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一...
  • Java中this和super的用法

    2020-11-02 17:45:10
    一、this的用法 构造方法是创建java对象的重要途径,通过new关键字调用构造器时,构造器返回...因此,构造方法也可以使用this代表“当前对象”。 书上对于this的描述: this表示一个对象的引用,它指向正在执行方
  • 业务需求,我们经常会判断是否为null而去做一些业务处理,用到了equals方法,但是你想想之前真的没有用错吗? 话不多说,这个经常用,直接上代码 package com.example; import lombok.extern.slf4j.Slf4j; ...
  • JAVA中this和super的用法

    2020-05-20 00:13:02
    <一>. this的用法  构造方法是创建java对象的重要途径,通过new关键字调用构造器时,构造器返回该类的对象,但是这个对手并不是完全由构造器负责创建.... 因此,构造方法也可以使用this代表“当前对象”
  • 但是 JavaScript 却同时存在undefined和null,这主要是由于历史原因,感兴趣的可以查一下。 二者的主要用法区别如下: undefined 变量被声明了,但没有赋值时,就等于undefined 调用函数时,应该提供的参数...
  • /** * 获得当月第一天的日期时间 yyyy-MM-dd HH:mm:ss * @param date * @return ... public static String getMonthFirstDate(Date...if (date == null) { date = new Date(); } Calendar c = Calendar.ge...

空空如也

空空如也

1 2 3 4 5 ... 18
收藏数 347
精华内容 138
关键字:

在java中null用法

java 订阅