Java的基础数据类型和String类的详解

Java基础知识点-2

Java基础知识点

1、Java虚拟机?为什么Java是平台无关的语言

Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。这与我们自身的系统是Windows、Liunx、Mac无关。

2、Java的基本类型,以及占用的字节问题

java中的基本类型有八种,分别是byte、short、int、long、char、float、double、boolean(String不是Java基本类型)

类型大小取值范围
byte一字节8位有符号整数-128 - 127
short二字节16位有符号整数-2^15 - 2^15-1
int四字节32位有符号整数-2^31 - 2^31-1
long八字节64位有符号整数-2^62 - 2^63-1
char2字节16位Unicode字符0 - 2^16-1
float四字节32位浮点数1.4E-45 - 3.4E+38,-1.4E-45 - -3.4E+38
double八字节64位浮点数4.9E-324 - 1.7E+308, -4.9E-324 - 1.7E+308
boolean一字节八位true,false

Unicode字符码:是Ascll字符编码的拓展,Ascll中每个字符用7位表示,计算机上每个字符8位。Unicode使用全16位字符编码,因此Unicode能表示世界上所有能用于计算机通讯的符号。

Unicode最初是作为Ascll的补充。若字符在Ascll中存在,则一个字节为空(全0),另一个字节为原Ascll码的值。

3、Java中的封装类

Java中有基本数据类型和基本数据类型的封装类,如int和Integer。为了方便将基本数据类型转化为对象进行处理,下面使用一段代码讲解:

public static void main(String[] args){
	Integer a = 100;
	//这里将a进行了自动装箱,封装成了对象,等同于Integer a = new Interger(1); 
	int b = a - 1;
	//这里将b进行了自动拆箱,将Java对象a转化成了基本数据类型然后进行计算。
	int x = 100;
	Integer y = 100;
	int z = 100;
	Integer f = 100;
    Integer g = new Integer(100);
    Integer h = new Integer(100);
    Integer j = 1000;
    Integer k = 1000;
	System.out.println("x == y");//结果为true
    System.out.println("x == z");//结果为true
	System.out.println("y == f");//结果为true
    System.out.println("g == h");//结果为false
    System.out.println("j == k");//结果为false
    //原因是Integer中IntegerCache这个类中的缓存数组cache[]存放内容为-128 - 127的整数,Integer x=100实际在内部做了Integer.valueOf(100),判断是否在这个区间,如果在此区间内,则返回x+128作为cache的下标,放到缓存中。如果不在这个区间,则创建new Integer(x)。即-128 - 127 内不会new生成,超出才另外new Integer()
    //如果是int与int值比较,Integer与int的值相同的比较,结果为true
    //如果是两个Integer=new Integer()比较,总是为false,地址不同
    //如果是Integer a=;Integer b=;若值在-128 - 127间true;不是则为false。
}

4、String类的详解

String不是Java的基本类型,其能保存字符串是因为其中定义了一个数组。

我们来看源码

public final class String 
    implements java.io.Serializable, Comparable<String>, CharSequence {
	private final char value[]; 
    private int hash; 
    private static final long serialVersionUID = -6849794470754667710L;
    。。。。。。
}

可以看到String类不可以被继承。String是final修饰的类,是不可以被继承的。String类实现了Serializable、 Comparable、CharSequence接口。分别是

Serializable:

//类的可序列化性由实现类的java.io类启用。类的可序列化性由实现java.io.serializable接口的类启用。不实现此接口的类将不具有序列化或反序列化的任何状态。可序列化类的所有子类型都是其自身可序列化。序列化接口没有方法或字段仅用于识别可序列化的语义
public interface Serializable {}

Comparable,这是一个比较接口:Java语言中建议所有需要实现比较功能的类都实现Comparable接口。

CharSequence:CharSequence类是java.lang包下的一个接口,此接口对多种不同的对char访问的统一接口;CharSequence类和String类都可以定义字符串,但是==String定义的字符串只能读,CharSequence定义的字符串是可读可写。

String中最常用到的equals方法,下面看一段代码

 public static void  main(String []args){
      String a = "pigpig";
      String b = "pigpig";
      String c = new String("pigpig");
      System.out.println(a == b);//输出结果为true
      System.out.pirntln(a == c);//输出结果为false
      System.out.println(a.equals(b));//输出结果为true
    }

各位肯定很疑惑,为什么a == b 为true,这就要说到Java语言规范中的字符串池,凡是内容一样的字符串常数,都引用同一个字符串对象,其值为常量的字符串,会通过String.intern()函数被限定为共享同一个对象。换句话说就是内存地址相同。

在上述例子中,a、b都是字符串常数(可以理解为不是new出来的),它们的地址分配相同,因此a == b为true。c由于是new出来的,因此其指向的地址与a有所不同,因此a == c为false。规范化的比较字符串应当使用equals()方法哦。

这里我们再展开讲String的拼接字符串问题,我们先来读一段程序

public static void  main(String []args){
      String s1 = "litlePig";
      String s2 = new String("litlePig");
      String s3 = "litle";
      String s4 = "Pig";
      String s5 = "litle" + "Pig";
      String s6 = s3 + "Pig";
      String s7 = s3 + s4;
      String s8 = new String("litlePig");
      System.out.println(s1 == s2);//false
      System.out.println(s1 == s5);//true
      System.out.println(s1 == s6);//false
      System.out.println(s1 == s7);//false
      System.out.println(s2 == s8);//false
      System.out.println(s1 == s6.intern());//true
      System.out.println(s1 == s7.intern());//true
      System.out.println(s2 == s2.intern());//false
}

然后我们引入几个概念

  • String s="xx"为字面量赋值形式,声明的数据会存入字符串常量池中;String s= new String(“xx”)为new+构造器模式,直接在堆中创建对象。
  • String常量创建时即创建final数组储存,值不可在变,String只读
  • 对String重新赋值时,开辟新空间进行存储,不会在原本的value存储空间内赋值
  • 常量+常量的结果仍然在字符串常量池中,变量+常量结果在堆中
  • 如果**拼接!!!**的结果调用intern()方法,返回值就在常量池中

然后我们打印出各个字符串的地址值加深上述概念的理解

String s1 = "litlePig";   System.out.println(System.identityHashCode(s1));//21685669
//值在字符串池中
String s2 = new String("litlePig");
System.out.println(System.identityHashCode(s2));//2133927002
//值在堆中
String s3 = "litle";
String s4 = "Pig";
String s5 = "litle" + "Pig";
System.out.println(System.identityHashCode(s5));//21685669
//常量+常量,值在字符串池中,根据String.intern()可得出与s1地址相同
String s6 = s3 + "Pig";
System.out.println(System.identityHashCode(s6));//1836019240
//变量+常量,值在堆中
String s7 = s3 + s4;
System.out.println(System.identityHashCode(s7));//325040804
//值在堆中
String s8 = new String("litlePig");
System.out.println(System.identityHashCode(s8));//1173230247

简单来说,字面量定义都在字符串池中,定义了就不可以改变值。非常量拼接的都会重新分配空间存储,但拼接的调用String.intern()与原字符串内容相等

new的都在堆中,new的即使调用String.intern()也不等于字符串池中的值

5、String、StringBuffer、StringBuilder的区别

上一个问题中我们已经知道String一经创建地址即固定,值不可在变。那么String、StringBuffer和StringBuilder有什么区别呢?话不多说看代码

public static void  main(String []args){
String s1 = "litle";
System.out.println(System.identityHashCode(s1));
s1 = "litlePig";
System.out.println(System.identityHashCode(s1));
//21685669
//2133927002
StringBuffer s2 = new StringBuffer("litle");
System.out.println(s2+"     "+ System.identityHashCode(s2));
s2.append("Pig");
System.out.println(s2 + "  " + System.identityHashCode(s2));
//litle     1836019240
//litlePig  1836019240
StringBuilder s3 = new StringBuilder("litle");
System.out.println(s3+"     "+ System.identityHashCode(s3));
s3.append("Pig");
System.out.println(s3 + "  " + System.identityHashCode(s3));
//litle     325040804
//litlePig  325040804    
}

可以看出StringBuffer和StringBuilder的值是可变的,是在原先的地址上加入新值。同时相对于String,StringBuffer和StringBuilder多出了一些方法,例如:

字符串反转

public synchronized StringBuffer reverse()

删除指定范围的数据

public synchronized StringBuffer delete(int start, int end)

插入数据

public synchronized StringBuffer insert(int offset, 各种数据)

StringBuffer采用同步处理,属于线程安全操作;而StringBuilder采用异步处理,属于线程不安全操作。

今天的学习就到这里,如有错误还望各位看官指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值