您的位置:首页 > Web前端

栋哥带你学Java单例与StringBuffer以及权限修饰符

2018-01-17 19:33 417 查看
一、单例

什么是单例?
单例也叫单实例,根据字面意思就可以看出只要单个实例,也就是只有一个对象.
单例的核心:在整个程序执行期间,有且只有一个该类的对象存在.
那我们需要怎么去保证只有一个实例呢?
1.不让外界来创建对象.
2.这个对象由我来创建(也不能让外界访问).
3.需要对外开放访问这个对象的方法.
那么都有哪些单例呢?
我把它分为五种,但是不是真正使用率比较高的应该只有两种,而且一般从事移动端的程序员才用得到.
(1)懒汉式
// 懒汉式1
class SingleObject {
// 定义一个私有化静态的本类对象
private static SingleObject singleObject;
// 构造方法私有化
private SingleObject() {}
// 对外开放公共的接口
public static SingleObject getSingleObject() {
if (singleObject == null) {
singleObject = new SingleObject();
}
return singleObject;
}
public void showMessage() {
System.out.println("我是懒汉1");
}
}
// 懒汉式2
class SingleObjectTwo {
// 定义一个私有化静态的本类对象
private static SingleObjectTwo singleObjectTwo;
// 构造方法私有化
private SingleObjectTwo() {}
// 对外开放公共的接口
public static synchronized SingleObjectTwo getSingleObjectTwo() {
if (singleObjectTwo == null) {
singleObjectTwo = new SingleObjectTwo();
}
return singleObjectTwo;
}
public void showMessage() {
System.out.println("我是懒汉2");
}
}
注意:在懒汉式中就有两种写法,而且这两种写法都差不多,第二种就是多了一个锁(synchronized).锁在后面会讲到,这篇博客就不说了,第一种在多线程中不安全,第二种安全,但是第一种效率比第二种高.只有你调用获取对象的方法,才有可能去创建对象.
(2)饿汉式
// 饿汉式
class SingleThree {
// 私有的静态对象初始化
private static SingleThree singleThree = new SingleThree();
// 私有化构造方法
private SingleThree() {}
// 对外开放接口
public static SingleThree getSingleThree() {
return singleThree;
}
public void showMessage() {
System.out.println("我是饿汉");
}
}
注意:饿汉式创建对象,是随着类的加载而创建这个对象.但是容易产生对象垃圾,造成内存的浪费.
(3)双检锁/双重校验锁
class SingleFour {
private volatile static SingleFour singleFour;
private SingleFour() {}
public static SingleFour getSingleFour() {
if (singleFour == null) {
synchronized (SingleFour.class) {
if (singleFour == null) {
singleFour = new SingleFour();
}
}
}
return singleFour;
}
public void showMessage() {
System.out.println("我是双检锁");
}
}
(4)登记式/静态内部类
// 登记式
class SingleFive {
private static class SingleFiveTest {
private static final SingleFive INSTANCE = new SingleFive();
}
private SingleFive() {}
public static final SingleFive getInstance() {
return SingleFiveTest.INSTANCE;
}
public void showMessage() {
System.out.println("我是登记式");
}
}
注意:多线程安全,一样能达到双检锁方式的功能.
(5)枚举
enum SingleSix {
INSTANCE;
public void whateverMethod() {}
public void showMessage() {
System.out.println("我是枚举");
}
}
注意:不初始化对象,多线程安全代码简单,自动支持序列号,防止多次实例化.
测试代码:
public class Demo {
public static void main(String[] args) {
//       懒汉1
//      SingleObject.getSingleObject().showMes
4000
sage();
//       懒汉2
//      SingleObjectTwo.getSingleObjectTwo().showMessage();
//       饿汉式
//      SingleThree.getSingleThree().showMessage();
//      双检锁
//      SingleFour.getSingleFour().showMessage();
//       登记式
//      SingleFive.getInstance().showMessage();
//       枚举
SingleSix singleSix = SingleSix.INSTANCE;
singleSix.showMessage();
SingleSix.INSTANCE.showMessage();
}
}


二、权限修饰符

权限修饰符的作用:设置访问权限
权限修饰符有哪些?
1.public(公开的)
2.private(私有的)
3.protected(受保护的)
4.默认的(default)什么都不写(例子:String name;)
那么每种权限符的权限都有哪些呢?
注意:√表示能访问到,×表示不能访问到.
本类   同包下的类 同包下子类  不同包下的类 不同包下的子类
public   √      √        √           √       √
private  √      ×        ×           ×       ×
protected√      √        √           ×       √
default  √      √        √           ×       ×


三、StringBuffer(字符串缓冲区)

StringBuffer干嘛用的呢?
StringBuffer相当于是一个可变的序列(操作的是原字符串),而String类则不能操作原字符串.
(1)
/**
* 无参创建StringBuffer
*/
public static void fun1() {
// 创建一个StringBuffer(拼接字符串用的)
StringBuffer stringBuffer = new StringBuffer();
// 获取容量(理论值) 默认值是16
System.out.println(stringBuffer.capacity());
// 获取长度
System.out.println(stringBuffer.length());
// 转化为字符串
System.out.println(stringBuffer.toString());
// 拼接字符串(操作的时原对象)
stringBuffer.append("fwekfew");
// 如果直接打印对象 系统会帮你调用toString方法
System.out.println(stringBuffer);
}
(2)
/**
* 插入和修改
*/
public static void fun2() {
// 直接使用字符串创建StringBuffer
StringBuffer sBuffer = new StringBuffer("fewffwefcaas");
// 插入一个字符 把字符插入到索引的位置上
// 插入boolean类型 就相当于把true和false当字符串插入
sBuffer.insert(sBuffer.length(), 'h');
System.out.println(sBuffer);
// 给索引位置进行 字符修改
sBuffer.setCharAt(0, 'k');
System.out.println(sBuffer);
// 注意:插入字符和修改字符的时候 不能越界
// 传入角标 返回字符
char charAt = sBuffer.charAt(7);
System.out.println(charAt);
// buffer转成字符数组
// 先变字符串 然后再变 字符数组
char[] charArray = sBuffer.toString().toCharArray();
}
(3)
/**
* 删除
*/
public static void fun3() {
StringBuffer sb = new StringBuffer();
sb.append("wanglong");
// 删除
//      sb.delete(0, 2);
// 注意: 开始坐标不能越界 结束坐标越界 系统当清空处理
System.out.println(sb);
//删除字符
//      sb.deleteCharAt(0);
//      System.out.println(sb);
// 反转
sb.reverse();
System.out.println(sb);
}
(4)
/**
* 字符串反转
*/
public static void fun4() {
// 从键盘输入一个字符串 反转
System.out.println("请输入一个字符串");
Scanner scanner = new Scanner(System.in);
String nextLine = scanner.nextLine();
// 转成StringBuffer
StringBuffer stringBuffer = new StringBuffer(nextLine);
// 反转
stringBuffer.reverse();
// 转化成字符串再输出
System.out.println(stringBuffer.toString());
}
(5)
/**
* 字符串实现Arrays.toString()的方法
*/
public static void fun5() {
int[] array = new int[]{1,2,3,4};
String string = "[";
for (int i = 0; i < array.length; i++) {
if (i != array.length - 1) {
string = string + array[i] + ", ";
}else {
string = string + array[i];
}
}
string = string + "]";
System.out.println(string);
}
(6)
/**
* StringBuffer实现Arrays.toString()的方法
*/
public static void fun6() {
int[] array = new int[]{1,2,3,4};
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < array.length; i++) {
if (i != array.length - 1) {
stringBuffer =
stringBuffer.append(array[i]).append(", ");
}else {
stringBuffer = stringBuffer.append(array[i]);
}
}
stringBuffer.insert(0, '[');
stringBuffer.append(']');
System.out.println(stringBuffer);
}
(7)
/**
*  替换
*/
public static void fun7() {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("ciwnffwefw");
// [start, end) 左闭右开
// 开始角标不能越界
// stringBuffer.replace(0, stringBuffer.length(), "aaa");
// System.out.println(stringBuffer);
// 字符串截取  返回了一个新的字符串给你
//[0,3]
// String substring = stringBuffer.substring(4);
// System.out.println(substring);
String substring = stringBuffer.substring(0, 4);
System.out.println(substring);
}
除了StringBuffer以外还有一个StringBuild.那么他们两者还有String之间的又有不同呢?
总结:
(一)StringBuffer和StringBuild区别
1.StringBuffer无论是在多线程还是单线程中使用都是安全的,相对于StringBuild来说效率低(耗费系统资源).
2.StringBuild在多线程中不安全,相对于StringBuffer来说效率高(耗费系统资源少).
3.StringBuffer和StringBuild的使用方一样.能用StringBuffer完成的事情,StringBuild一样能完成,前提是单线程环境下.
(二)String和StringBuffer的区别
1.String是不可变的,多线程环境下不安全.
2.StringBuffer是可变的,操作的是对象本身.
3.String和StringBuffer作为方法的参数时是有区别的,String作为参数时,传进去的相当于是值的传递,而StringBuffer传入的则是地址.
注意:所有的引用数据类型当中,就String作为参数时是当一个值传入.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息