>>分享Java编程技术,对《Java面向对象编程》等书籍提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 20759 个阅读者 刷新本主题
 * 贴子主题:  面试必考-static、final和单例模式 回复文章 点赞(0)  收藏  
作者:sunshine    发表时间:2020-03-08 15:40:28     消息  查看  搜索  好友  邮件  复制  引用

                                                                                                

面试必考-static、final和单例模式

     static

     那天我朋友问了我个问题,static和单例模式有什么区别,所以我觉得static可以讲一下

     他的问题是,把对象弄成static是不是就不变了

     显然,这是还没弄清楚引用和对象的区别

     点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

      其实存放在静态区中的是引用,而不是对象。而对象是存放在堆中的。如果有这样一句话

                   public static final Book   book =   new Book();

      意思就是book这个引用,指向了这个new出来的对象。

     static的引用和正常的引用有什么区别?

     当你加载了这个类的时候(第一次使用这个类的时候会加载这个类到jvm),这个static引用会率先被加载。所以,当我们第一次调用Book.book的时候,这个静态的book引用就会一直存放在静态区里了(当fullGC回收整个类才会销毁这个引用)。

     而正常的引用,只能通过new出一个对象后才能使用,所以当对象被回收了,这个引用自然也回收了(而且非静态引用如果是方法中的引用,会存放在函数的栈里;如果是对象的引用,会和对象一起存放在heap里)。

     final

     final定义了之后,你就必须在一开始就需要赋值,所以上面那行代码就必须在一开始就赋值。而如果你想延迟加载,提高性能,那么就不可以用final。

     单例模式

     单例模式是如果实现的,就是通过调用这个类里的一个静态方法,弄一个if语句判断一下,如果有实例了,就返回这个实例,如果没有,就创建这个实例。其实并没有多大的技术含量。

     第一种,最基本的思维。

public class Book {
     private static Book  book =   new Book();
     private Book() {}
     public static Book getInstance() {
         if ( book ==   null) {
             book =   new Book();
        }
         return book;
    }
}

              这里为什么要判空呢?因为你这个是静态的,所以其他地方完全有Book.getInstance = null;的可能。

                 第二种,这里使用final,让引用的指向不可变,这样就不需要判空了

public class Book {
     private static final Book   book =   new Book();
     private Book() {}
     public static Book getInstance() {
         return book;
    }
}

                  第三种,延迟加载(线程不安全,假如有多个同时发现是空的,会创建出好多实例)

public class Book {
     private static Book  book;
     private Book() {}
     public static Book getInstance() {
         if ( book ==   null) {
             book =   new Book();
        }
         return book;
    }
}

                  第四种,添加线程安全功能,加一个关键字就可以

public class Book {
     private static Book  book;
     private Book() {}
     public static synchronized Book getInstance() {
         if ( book ==   null) {
             book =   new Book();
        }
         return book;
    }
}
这个方法在多线程下的工作表现很出色

                               第五种,规避不需要的同步,因为上面的同步范围太大,有点浪费性能,在引用有指向的时候,是不需要同步的
public class Book {
     private static Book  book;
     private Book() {}
     public static synchronized Book getInstance() {
         if ( book ==   null) {
             synchronized (Book. class) {
                 book =   new Book();
            }
        }
         return book;
    }
}

                  第六种,静态内部类

public class Book {
     private Book() {}
     public static synchronized Book getInstance() {
         return BookHolder. book;
    }
     private static class BookHolder {
         private static final Book   book =   new Book();
    }
}

                  第七种,枚举单例

public class Book {
     private Book(){}
     public static Book getInstance() {
         return BookEnum. BOOK.getInstance();
    }

     private static enum BookEnum {
         BOOK;
         private Book   book;
         private BookEnum() {
             book =   new Book();
        }
         public Book getInstance() {
             return book;
        }
    }
}
最优,但是枚举这个东西可读性不高

具体选择什么,看情况

                                                                                                        
----------------------------
原文链接:https://blog.csdn.net/qq_36523667/article/details/79014324

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2020-03-08 23:21:56 重新编辑]
网站系统异常


系统异常信息
Request URL: http://www.javathinker.net/WEB-INF/lybbs/jsp/topic.jsp?postID=2652

java.lang.NullPointerException

如果你不知道错误发生的原因,请把上面完整的信息提交给本站管理人员