• JAVA基础知识之数据类型


    JAVA的数据类型知识点主要包括基本数据类型,包装类,字符串类(String,StringBuffer, StringBuilder区别和用法),数组,数据类型转换等等,暂时只想到这么多,后面会再补充。

    1.基本数据类型

    重点是JAVA变量分为原始变量和包装变量,另外变量初始化时要注意变量类型能表示的范围以及精度的损失。

    a.八种基本类型为 byte(8bit), short, int(32bit), long, float, double, boolean, char

    b.对应封装类型为Byte,Short,Integer,Long,Float,Double,Boolean,Character

    c.Java中的数值类型都是有符号的,取值范围是固定的,不随硬件环境和操作系统改变。

    d.封装类和原始类型有以下不同点

    • 原始类型做参数传递时是值传递,封装类型是按引用传递
    • 封装类的对象初始值是null,但原始类型的变量的默认值不是。(int默认初始化为0)

    e.Java中直接写的小数是double类型,直接写的整数是int类型,因此要注意类型转换时的精度损失以及表示范围,例如

    • float f = 3.4 是会有精度损失的,正确写法是 float f = (float)3.4 或者 float f = 3.4F
    • int a = 3; long b = a;  int类型无法表示一个非常大的数,应写成  long b = aL 或者 long b = (long) a   ???

    f.null表示什么?如何理解String x = null

    null仅仅表示该引用目前没有指向任何对象,编译器不会分配内存, null是将引用变量的值置0. 

    字符串类

    Java字符串存储机制(内存分配方式)

    对于String s1 = new String("abc"); String s2 = new String("abc"); 

    两个引用对象s1和s2虽然内容相同都是"abc",但是s1和s2指向堆内存中不同的对象。


    对于String s1 = "abc"; String s2 = "abc"

    s1和s2引用的是同一个常量池中的对象,即,如果常量"abc"的对象已经存在【判断依据是equals(Object obj)的返回值】,则不会创建新的对象。

    总结如下

    String s1 = "abc";// s1指向常量区字符串对象"abc"

    String s2 = "abc";// s2也指向常量区字符串对象"abc", s1和s2指向的是常量区的同一个对象,因此这里不会创建新对象

    String s3 = new String("abc");// s3指向在堆中创建的新对象,此对象内容为abc

    String s4 = new String("abc");// s4指向在堆中创建的另一个新对象,此对象内容为常量区的abc,但是s3和s4各自指向堆中不同的对象


    典型面试题:

    1.String s = null 和String s = ""是否相同?

    答,不同。对于s = null,是定义一个字符串类型的引用,但是它不指向任何一个字符串对象。

    对于s = ""; s是一个字符串的引用,它指向了另一个字符串对象,而且那个对象的内容为"",即空串。


    2. new String("abc") 创建了几个对象

    答,一个或两个。new会创建一个。另外,如果常量池中已经有"abc"字符串,就不会再在常量区创建一个字符串对象,反之如果常量区还没有"abc"字符串对象,就会在常量区再创建一个字符串abc。


    字符串的比较 == , equals 和 hashCode

    == 用来直接比较两个变量对应的值是否相等

    例如,如果两个变量都是基本类型的变量,则是直接比较他们的值是否相等,如果两个变量指向的是对象类型的变量,则是比较这两个对象的首地址是否相等。

    equals通常用来比较对象

    equals方法是可以被子类覆盖的,如果没有覆盖,默认equals也是用==的方式做比较,比较的是对象首地址,首地址相同,则这两个对象是同一个对象。

    而被覆盖后的方法就不一定了,例如String类中的equals,是比较对象指向的内容,而不是比较对象的首地址。

    所以对于 String s1 = new String("abc");String s2 = new String("abc");  s1==s2  为false, 但是 s1.equals(s2)为true.

    hashCode,如果hashCode没有被重写过,就返回该对象地址的编码值,否则是用来返回一个对象编码后的int值

    那么为什么需要重写hashCode呢,这是为了保证与hash有关的集合类数据的一致性(HashSet, HashMap等)

    首先来看看hashSet的put流程,先判断对象的hashCode在HashSet中是否已经存在,如果不存在,则存入对象;如果存在,则在用equals

    判断一下该对象和存在的对象是否相等,如果相等,则不再插入;如果不相等,则根据具体算法将对象存放其他地方。(相同hashCode索引的对象,按链表存放?)


    那么现在的问题是,在HashSet中,判断两个对象是否相等是用equals的,这要求在equals判断相等时,hashCode也必须相等才能在逻辑上符合对象相等。

    假如两个对象通过equals相等,但是hashCode不相等,那么在HashSet中就会出现重复对象,这是不符合HashSet特征的。

    所以就要求,在重写了equals方法之后,也必须重写hashCode方法,使得equals与hashCode符合下面的要求,

    对于equals()相等的两个对象,其hashCode()返回的值一定相等

    同时还能得到,对于equals不相等等两个对象,其hashCode可能相等,也可能不等(参见前面Hash容器存储原理)


    String, StringBuffer, StringBuilder的区别

    String

    String是不可变类,一旦创建则不可以修改。String在实例化时可以用构造方式或者赋值方式。

    StringBuffer

    对象创建后仍然可以修改值。如果要修改String对象的值(内容),值能借助StringBuffer间接实现,但是会产生额外临时对象,影响效率。

    String修改原理如下。

    String s = "hellow"; s+="World";

    以上代码等价为:

    StringBuffer sb = new StringBuffer(s);

    sb.append("world"); s = sb.toString();

    下面来验证这个结论:

    String s= "hellow"; 

    String stmp = s;

    s+="World";

    System.out.println(stmp==s);//输出false


    第二个

    StringBuffer sb = new StringBuffer("hellow");

    StringBuffer sbtmp = sb;

    sb.append("world"); 

    System.out.println(sbtmp==sb);//输出true

    StringBuilder

    与StringBuffe相似,都支持字符串修改,都在字符串缓冲区进行。区别是StringBuilder不是线程安全的。

    因此这三个字符串类的执行效率是 StringBuilder >  StringBuffer > String.

    因此如果操作数据比较少,优先用String,如果单线程下数据量比较大,优先用StringBuilder, 如果在多线程下操作大量数据,则用StringBuffer.


     

    数组

    • Java中数组是不是对象:Java中的数组不仅有属性(length等),也有自己的方法(clone等),从这个角度来说JAVA数组是对象。
    • JAVA数组的初始化
    • type arrayName[];  或者  type[] arrayName
    • 与C++不同的是,JAVA数组被创建后会默认初始化,例如int类型会将元素初始化为0,对象则会初始化为nll
    • JAVA数组在定义时,不会为数组元素分配存储空间,因此[]中不需要指定长度。而在使用时需要分配空间,例如: arrayName = new type[size]
    • length属性与length()方法的区别
    • length属性用来获取数组的长度
    • length()方法用来计算字符串长度。


    数据类型转换


    基本数据类型转换

    JAVA基本数据类型转换分两种

    1.自动转换

    从存储范围小的类型到存储范围大的类型

    自动转换也叫隐式转换,由JVM自动完成,不需要额外编程,

    具体规则为:byte→short(char)→int→long→float→double

    例如: byte b = 10; short sh = b;   byte自动向short类型转换


    2.强制转换

    从存储范围大的类型到存储范围小的类型

    需要显示地进行类型转换,

    具体规则为:double→float→long→int→short(char)→byte

    例如  double d = 3.10; int n = d;   double强制转换成int,(虽然没有语法错误了,但是还是会有精度损失,不同类型损失精度也不同)

    注意,默认情况直接写小数,JVM会认为是double类型,直接写整数,会默认为int类型,

    所以 float f = 3.4是无法通过编译的,需要写成 float f = (float)3.4, 或者 float f = 3.4F;

    short sh = 5也是无法通过编译的,要写成short sh = (short)5;


    基本数据类型和包装类之间的转换

    string->byte
    Byte static byte parseByte(String s)
     
    byte->string
    Byte static String toString(byte b)
     
    char->string
    Character static String to String (char c)
     
    string->Short
    Short static Short parseShort(String s)
     
    Short->String
    Short static String toString(Short s)
     
    String->Integer
    Integer static int parseInt(String s)
     
    Integer->String
    Integer static String tostring(int i)
     
    String->Long
    Long static long parseLong(String s)
     
    Long->String
    Long static String toString(Long i)
     
    String->Float
    Float static float parseFloat(String s)
     
    Float->String
    Float static String toString(float f)
     
    String->Double
    Double static double parseDouble(String s)

    Double->String
    Double static String toString(Double)

    基本


  • 相关阅读:
    Android应用性能优化
    打造高质量Android应用:Android开发必知的50个诀窍
    毕向东day23--java基础-网络总结
    《编写高质量代码:改善Java程序的151个建议》
    最新java数组的详解
    主线程中一定不能放耗时操作,必须要开子线程,比如下载文件,不然会不让你拿到输入流--报错显示android.os.NetworkOnMainThreadException
    《Head First设计模式(中文版)》
    码表由来:ascll码-Gbk2312-GBK-Unicode-UTF-8
    《Java程序性能优化:让你的Java程序更快、更稳定》
    LeetCode 147. 对链表进行插入排序
  • 原文地址:https://www.cnblogs.com/fysola/p/6017190.html
Copyright © 2020-2023  润新知