菜鸟学JAVA之——String、StringBuffer及 基础数据类型的对象类型

一、String

String:是一个字符的容器,既然是一个容器 ,他一定符合容器的基本操作:求长,定位,替换

String的两种创建对象的方式

String str = "zhangaoqi";
String str1 = new String("zhangaoqi");

内存实现:

在这里插入图片描述

这两个创建的str不一样,不是同一个对象

public class Test1{
    public static void main(String[] args){
        String str = "zhangaoqi";
        String str1 = new String("zhangaoqi");
        String str2 = "zhangaoqi";
        String str3 = new String("zhangaoqi");
        System.out.println(str == str1);//输出false
        System.out.println(str == str2);//输出true
        System.out.println(st1 == str3);//输出false
        System.out.println(str.equals(str1);//输出true
    }
}
  • str == str1,输出false

    这是因为 == 判断的是地址,str直接指向常量池得地址,而str1先指向堆的对象再指向常量池,地址不一样,所以输出false。

  • str == str2,输出true

    这是因为常量池已经出现的数据不会出现第二次

  • st1 == str3,输出false

    这是因为有new,又先创建了一个对象,新开辟了一个空间,所以地址不一样了

  • 如果只需要对比字符串的内容而不是地址,则使用equals()方法

  • 从以上例子中也可以看出 ==与 equals的区别

注意:

public class Test2{
    public static void main(String[] args){
       int a = 3;//3在常量池中
       int b = 3;//3在常量池中,与a指向的一样
       System.out.println(a == b);//输出true   常量池中的内容可用 == 比较
    }
}

因为String有两种赋值方式,这时引入四类八种,它们有没有类,int也有两种复制方式吗?

所有基础数据类型的对象类型都有两种赋值方式:直接写和创建对象赋值

String的一些方法

//String的一些方法
String str = "zhangaoqi";
System.out.println(str.concat("aaa"));//字符串拼接 
System.out.println(str.contains("zhang"));//true    判断是否包含zhang字符串   
System.out.println(str.startsWith("zh"));//true   判断是否以zh开始

注意String的replace()方法和replaceAll()方法的区别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hUI7esb5-1573565802967)(C:\Users\张澳琪\AppData\Roaming\Typora\typora-user-images\image-20191112213347222.png)]
工作中常用的一个操作

如果一个前端传过来文件的编码是GBK的,你看到的是乱码的,则需要先把他转换为字节的数据,然后重新创建String对象,按GBK方式编码。(电脑只认识二进制,将字符串转为字节,再用另一个编码方式编回来)

public class Test3{
    public static void main(String[] args){
        	String str = "张澳琪";
            byte[] arrays = str.getBytes();
            try {
                String str2 = new String(arrays,"GBK");
                System.out.println(str2);  //输出:娑ㄥ晩浜插摝
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
    }
}

二、StringBuffer

StringBuffer:用来对字符串进行操作

字符串一旦定义则不可改变,这时直接操作字符串会遇到一个效率损耗问题

例如:有两个字符串a,b需要拼接,拼接完后会有三个对象(不考虑栈),原来a存在在常量池,b存在在常量池,新拼接出来的字符串还需要放在常量池。如果有5个字符串拼接则需要9个对象,执行效率低。

对String常用类的两个操作工具StringBuffer和StringBuilder,这两个工具的方法没太大区别,只是一个是线程安全的一个是线程不安全的

public class Test4{
    public static void main(String[] args){
        StringBuffer sb = new StringBuffer("zhang"); 
        System.out.println(sb);//输出 zhang
        sb.append("ao");
        System.out.println(sb); //输出 zhangao
        sb.delete(1,3);//从角标1开始删,删(3-1)个,结果为 zngao  这是因为StringBuffer的内容而可以改变
        sb.reverse();
        System.out.println(sb); //输出 oagnz
        sb.insert(1,"ha"); //从角标1开始插,插ha
        sb.toString();//将StringBuffer型转为字符串型
    }
}

StringBuffer创建的对象内容可以改变,而String一旦定义内容不可变!

public class Test5{
    public static void main(String[] args){
        String str = "zhangaoqi";
        str.replace('z','c');
		System.out.println(str);//输出还是zhangaoqi,这是因为str的内容不能变
                                //replace()方法是返回了一个新的字符串
        String a = str.replace('z','c');
        System.out.println(a);//输出 changaoqi
        
        StringBuffer sb = new StringBuffer("zhang"); 
        sb.reverse();
        System.out.println(sb); //输出 gnahz ,内容可以改变
    }
}

练习一下
判断字符串是否是回文字符串(用StringBuffer实现)

import java.util.Scanner;
public class BackString {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String temp = sc.next();
        StringBuffer str = new StringBuffer();
        str.append(temp);
        String result = str.reverse().toString();
        System.out.println(result.equals(temp));
    }
}

三、基础数据类型的对象类型

Integer

  • int是Integer 的缩写
  • Integer是int的对象类型
public class Test6{
    public static void main(String[] args){
       Integer a1 = 3;
       Integer a = new Integer(3);
       Integer b = 3;
       int c = 3; //基础数据类型
       System.out.println(a1);//输出3
       System.out.println(a == a1);//输出false
       System.out.println(a == b);//输出false    一个在堆中,一个在常量池中
       //只要是基础数据类型就只比较内容
       System.out.println(b == c);//输出true
       System.out.println(c == a);//输出true//这里因为c是基础数据类型,没有equals比较方法     
    }
}

Integer的一个诡异的地方

public class Test7{
    public static void main(String[] args){
       Integer a = 14;
       Integer b = 14;
       System.out.println(a == b);  //输出true
       
       Integer c = 144;
       Integer d = 144;
       System.out.println(c == d);  //输出false
    }
}

这是因为Java的JVM一开始在静态常量池里面创建了256个值(-128,127),这些值一开始就存在在常量池里,这时等于127以内的值指向同一个值,但是如果大于127后,它指向了不同的地址,这就相当于new一个对象的过程,这就是Integer不同的地方,所以int类型的数据比较大小时应该用基础数据类型比较。

总结

  • int和int之间,用== 比较,肯定为true。基本数据类型没有equals方法
  • int和Integer比较,Integer会自动拆箱,== 和 equals都肯定为true
  • int和new Integer比较,Integer会自动拆箱,调用intValue方法, 所以 == 和 equals都肯定为true
  • Integer和Integer比较的时候,由于直接赋值的话会进行自动的装箱。所以当值在[-128,127]中的时候,由于值缓存在IntegerCache中,那么当赋值在这个区间的时候,不会创建新的Integer对象,而是直接从缓存中获取已经创建好的Integer对象。而当大于这个区间的时候,会直接new Integer。
    • 当Integer和Integer进行== 比较的时候,在[-128,127]区间的时候,为true。不在这个区间,则为false
    • 当Integer和Integer进行equals比较的时候,由于Integer的equals方法进行了重写,比较的是内容,所以为true
  • Integer和new Integer : new Integer会创建对象,存储在堆中。而Integer在[-128,127]中,从缓存中取,否则会new Integer.
    所以 Integer和new Integer 进行==比较的话,肯定为false ; Integer和new Integer 进行equals比较的话,肯定为true
  • new Integer和new Integer进行== 比较的时候,肯定为false ; 进行equals比较的时候,肯定为true
    原因是new的时候,会在堆中创建对象,分配的地址不同,==比较的是内存地址,所以肯定不同
  • 装箱过程是通过调用包装器的valueOf方法实现的
  • 拆箱过程是通过调用包装器的xxxValue方法实现的(xxx表示对应的基本数据类型)
  • 总结:下面的Byte、Short、Integer、Long这几个类的valueOf方法实现类似的。所以在[-128,127]区间内,==比较的时候,值总是相等的(指向的是同一对象),在这个区间外是不等的。
    而Float和Double则不相等, Boolean的值总是相等的

Byte

public class Test8{
    public static void main(String[] args){
       Byte a = 3;
       Btye b = new Byte((byte)3);//这里需要强转是因为如果直接写3默认是int型
       System.out.println(a);  //输出3
       System.out.println(b);  //输出3
       System.out.println(a == b);  //输出false 一个申请空间了一个没有
       System.out.println(a.equals(b));  //输出true
       
    }
}

Short、Long

public class Test9{
    public static void main(String[] args){
       Short a = 3;
       Short b = new Short((short)3);//这里需要强转是因为如果直接写3默认是int型
       System.out.println(a);  //输出3
       System.out.println(b);  //输出3
       System.out.println(a == b);  //输出false 一个申请空间了一个没有
       System.out.println(a.equals(b));  //输出true
       Long a1 = 3L;
       Long b2 = new Long(3);
       System.out.println(a.equals(b));  //输出true 
    }
}

Float、Double

public class Test10{
    public static void main(String[] args){
       Float f = 3.4f;
       Float a = 3.4f
       System.out.println(f == a);  //输出false  这是因为浮点型根本不能确定精度
        //f可能是3.400000000000001f   a可能是3.400000000000002f 
       System.out.println(f.equals(a);//输出true  这是因为此时只是根据字面量来比较的 
       
      	Double d1 = new Double(3.4);
        Double d2 = 3.4;
        System.out.println(d1 == d2);  //输出false                  
    }
}

Character

public class Test11{
    public static void main(String[] args){
       Character c = 'c';
       Character a = new Character('c');
       System.out.println(a == c); //false
       Character b = 'c';
       System.out.println(a == c); //true   char不是浮点型的
    }
}

Boolean

public class Test12{
    public static void main(String[] args){
       Boolean b = false;
       Boolean a = new Boolean(false);
       Boolean c = false;
       System.out.println(a == b); //false
       System.out.println(b == c); //true   Boolean不是浮点型的
    }
}

基础数据类型的对象类型到底用来干什么?

常用的一般不用它来做业务,用它来作为辅助该种类型变量的工具来使用

eg:有一个字符串,想把字符串型变为其他型

	int a = Integet.parseInt("55");//可以直接调用parseInt()方法是因为他是静态方法
    System.out.println(a); //输出55
	int a = Integet.parseInt("a5");  //不行
	byte b = Byte.parseByte("55");
	double b = Double.parseDouble("55");
	boolean b = Boolean.parseBoolean("55");
	byte b = Integet.parseByte("55");

注意:Character没有parseCharacter()方法,因为本来就有charAt(0)方法可以把字符串转为字符,所以没必要再有parseCharacter()方法。

其他方法工具

public class Test13{
    public static void main(String[] args){
       System.out.println(Integer.compare(13,14)); //输出-1,如果大于零则前面的大于后面的
	   System.out.println(Integer.bitCount(4)); //输出1,看数占了几位,所有的0都不数
        System.out.println(Integer.decode("0x05"));//将字符串中的16进制转为10进制int型
        System.out.println(Integer.reverse(50)); //输出:1275068416   将int型的二进制数反转过来
        System.out.println(Integer.MIN_VALUE);//最小值
    }
}
//Double、Float...等的方法都类似

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值