Java学习笔记门外篇:数据类型

来源:互联网 发布:淘宝如何上传宝贝视频 编辑:程序博客网 时间:2024/06/05 18:56

一、类 型

1.范围与转换相关

数据类型 关键字 内置类 范围 占字节 默认值 字节型 byte Byte -27 ~ +27=-128~127 1字节: 8bit 0 短整型 short Short -215~+27 2字节: 16bit 0 整型intInteger-231~+231 4字节: 32bit 0 长整型 long Long -263 ~ +263 8字节: 64bit 0L 字符型 char Character JDK1.8中Java的字符采用Unicode6.2编码,
JVM采用UTF-16Big Endian。
Unicode范围为‘\u0000’到‘\uffff’,
整数范围是0~65535。
例如,65代表‘A’,97代表‘a’
2字节: 16bit ‘\u0000’
Null 单精度浮点型 float Float Float.MIN_EXPONENT:-126 ~ Float.MAX_EXPONENT:127 4字节: 32bit 0.0F 双精度浮点型double DoubleFloat.MIN_EXPONENT:-1022 ~ Float.MAX_EXPONENT:1023
(浮点数默认为double)
8字节:64bit 0.0D 字符型 boolean Boolean false  &   ture 1字节: 8bit false 类 className各类类型的类名     Null

2.符号的简要使用

格式控制符与算术运算符

格式控制符 表示 算术运算符 按优先级表示 %d 以十进制格式转出 . [] () , ; %e  %E 以科学记号浮点数输出 单目 ++,–,~,! %o  %O 以八进制整数格式控制 乘除 /,%,*,+,- %x  %X 以十六进制整数格式输出 位运算 <<,>> %s  %S 以字符串格式符号输出 关系符号 >,<,>=.<=,==,!= %c  %C 以字符符号输出 逻辑符号 &,^,|,&&,||,?: %b  %B 以boolean型输出 赋值符号 =,+=,-=,/=,*/,%=

像这类符号可以举出非常多到用时查找即可在此仅仅列出部分

3.进制转换与表示格式

举个例子一目了然 :

int number1 = 12;//十进制 int number2 = 014;//八进制 int number3 = 0xc;//十六进制 //浮点数除用小数表示还可用科学记号法表示 double number4 = 0.00123; double number5 = 1.23e-3; //若要表示字符,则需要使用“'”符号 char size = 'M'; char name = '麦克喵'; //对于常量的一种表示方法,为使表示更加清晰 int number7 = 1234_5678; double PI = 3.141_592_653; 

4.使用java.util.Scanner与java.math.BigDecimal标准类

1.使用java.util.Scanner

如果是要在命令提示符模式下取得用户输入,基本上可以使用System.in对象的read()方法,不过这个方法返回int类型。
此时可以通过Scanner来代劳:

import java.util.Scanner;//导入类,以下即可简写Scanner scan = new Scanner (System.in);//建立Scanner实例int num = scan.nextInt();//获取输入的下一个整数

Scanner的nextInt()方法会先看看标准输入中有无下一个字符串(以空格或换行符分隔),有的话则尝试剖析为int类型,Scanner对每个基本类型都有对应的next__( )方法,如nextByte()、nextDouble()等,如果是直接取得字符串,则使用next(),如果取得用户输入的整行文字(以换行分隔),则使用nextLine()。

2.使用java.math.BigDecimal()

  • 由于Java遵循IEEE754浮点数运算规范,使用分数与指数表示浮点数,如0.75会用1/2+1/4表示,0.875会用1/2+1/4+1/8来表示,而0.1会1/16+1/32+1/256+1/512+1/4096+1/8192无限循环下去,无法精确表示而造成运算误差。所以1.0-0.8d 结果在Java、Python、JavaScript语言中也并非得到0.2。故当需要精确计算时要小心使用浮点数,而且也不要用==来比较浮点数运算结果。
  • 由上,为了获得更好的精确度,可以使用BigDecimal标准类,它提供有plus()、subtract()、multiply()、divide()方法进行加减乘除运算,add()加运算,equals()比较两个BigDecimal实质上是否相同。
import java.math.BigDecimal;BigDecimal operand1 = new BigDecimal("1.0");BigDecimal operand2 = new BigDecimal("0.8");BigDecimal operand3 = new BigDecimal("0.2");BigDecimal num = new BigDecimal("2.0");BigDecimal result = operand1.subtract(operand2);if(op1.add(op2).add(op3).equals(num)){    System.out.println("op1、op2、op3的和等于num");    }

4.对象指定与相等性

Java并非完全的面向对象程序语言,在Java中有两大类型系统,即基本类型和类类型 。初学者必须区分=,==运算用于基本类型和类类型的不同。

  • 当=用于基本类型时,是将值赋给变量,当==用于基本类型时,是比较两个变量所储值是否相等。
  • 当在操作对象时,=是表示指定名称adc参考自某个对象,==是指比较两个名称是否参考自同一个对象。!=恰相反,表示两个对象参考自不同对象。
  • 从内存的实际运作方面来看,用于基本类型和对象类型,并无不同,都用作比较两个单元引用是否来自同一个地址。
  • 进一步的,若比较不同对象或者相同对象的内容值而不关注对象参考时,所用的操作equals()方法更加合适。

二、类类型

1.自动装箱

使用基本类型是出于效率,但更多时候需要基本类型像对象一样被操作。
使用Long、Integer、Double、Float、Boolean、Byte、Short、Character等类打包器。Wapper将基本类型打包到对象中,特殊的Number类对所有类型进行一般化的自动装箱(多态),示例如下:

int data = 20;Integer wrapper1 = new Integer(data);//使用new新建打包器对象int i = 20;Integer wrapper2 = i;//进一步使用自动装箱功能Integer wrapper3 = 15;int wrap3 = wrapper3;//自动拆箱Double val = wrapper3.doubleValue()/3//操作Integer类的doubleValue方法将打包值以double类型返回System.out.println(wrapper1.compareTo(wrapper2));//操作打包器方法与另一个对象的值进行比较,相同返回0,小于返回-1,大于返回1Number num = 2.71828f;//使用一般化Number类Integer i = 10;System.out.println(i+10);//i会自动拆箱进行加法运算输出20System.out.println(i++);//i会先自动拆箱先输出10,再自增运算

2.自动拆箱内幕

自动装拆箱其实是一种编译程序语法糖(Compiler Sugar),通过将一些步骤的操作封装到类中达到简化使用的效果。
引入: 当我们如下操作时程序运行结果会出现不同

        Integer i1 = 100;        Integer i2 = 100;        System.out.println((i1 == i2)? "ture":"false");//返回ture        Integer i3 = 200;        Integer i4 = 200;        System.out.println((i3 == i4 )?"ture":"falst");//返回false

代码不过是将100改到200但执行的效果却不同,那么这个自动装箱语法糖究竟干了什么?实际上程序会使用Integer.valueof()来建立Integer实例,调用Integer类中的valueof()方法,源码如下

public static Integer valueof(int i){    if(i>=IntegerCache.low && i<=IntegerCache.high)        return IntegerCache.cache[i + (-IntegerCache.low)];    return new Integer(i);}

很明显,通过自动装箱到Integer过程中,判断了一个IntegerCache的范围值,Integer的缓存(Cache),默认为byte的可改范围内(-128~127),在此范围内,若有已分配有同值的实例,新的实例并不会分配新的空间储值,而是直接引用已有实例的空间地址。而在超过此范围时都会重新生成新的实例。
故,在比较类类型的值时,使用equals()方法更具有保险性。

3.特殊的类类型

enum:枚举类关键字,enum定义了特殊的类继承自java.lang.Enum;其实也是Java中的一种语法糖。

public enum Action{    A,B,C,D}//反编译//注意:直接继承自Enum类的程序会被编译器拒绝这里模拟反编译import java.lang.Enum;public final class Action extends Enum{    private Action(String s, int i){                    super(s,i);}//类构造器权限private,只有内部能实例化    public static final Action A;    public static final Action B;    public static final Action C;    public static final Action D;    //将存入的值定义为静态常量方便实例化后调用    ...    static{//在静态代码块中实例化为带序号的对应名称对象        A = new Action("A",0);        B = new Action("B",0);        C = new Action("C",0);        D = new Action("D",0);    ...    }}

在使用时,可直接当作静态常量调用,当方法定义为接收此类类型的参数时,传入时只能输入声明时定义几个的常量。

三.对象初步

1.数组对象

数组:用来接收数据,具有索引的数据结构。

int[] array1 = {1,15,45} ;//声明有三个元素空间的数组并赋初始值int[] array2 = new int[2];//声明2个连续空间的int数组      array2[0] = 45;      array2[1] = 782;int[] array3 = new int[]{46,4564,4546,87} for(int i = 0;i<array1.length;i++){//利用for循环获取数组中的值    if (myList[i] > max)  //获取最大值        max = array1[i];         } System.out.println(max);for(int s:array2){//增强型for循环是一种语法糖    int total += s; //计算元素之和    System.out.println(total);     }int[][] array3 = int[2][3];//多维数组的声明int[][] array4 = {{147,848,456},{546,787,834,628,952}};//多维数组可看作矩阵,显然它并不完全是,实际上你也可以建立不规则数组int[][] array5 = new int[2][];        array5[0] = new int[]{54,66,48};        array5[1] = new int[]{45,465,62,89};
  • 既然数组也是对象,int[]即是类名称,new方法即创建了int类型的数组实例,即int[]类的对象
  • 多维数组也可理解为int[]类型的一维数组实例,即int[][]的对象.这样就理解了数组的多维实际上是一维数组的嵌套层叠
  • 使用new新建一个数组时,其每个索引元素都会有默认值(参见本文第一部分)。若默认值需更改,可使用java.util.Arrays的fill()方法来设定新建数组的默认值。
  • 特别注意:当声明一个类数组时,eg:Integer[] arr = new Integer[3]; 只声明容量而未赋值的时候,实际上并没有创建出任何对象。多维情况时同样适用。

2.数组复制

在Java中,数组自建立时长度即固定,若长度不够使用,需另建新的数组将原数组复制至新数组中。

  1. 浅层复制(Shallow Copy)

    使用System.arrayCopy()方法可对数组进行选择复制,它接收五个参数:来源数组,来源起始索引,目的数组,目的起始索引,长度。
    JDK1.6以上还可用Arrays.copyOf()方法更加方便的复制数组,并自行建立新数组存储起来

    int[] s1 = {45,82,84,215,45,98,27,54};int[] s2 = new int[s1.length];System.arrayCopy(s1,0,s2,0,s1.length);int[] s3 = Arrays.copyOf(s1,s1.length*2);//第二个参数即为新数组长度

然而实际上,以上两种方法用在类类型声明的数组时,都是执行浅层复制,即只复制数组的指针参考,并没有实际复制出对象。当改变其中一个数组的元素,会使因其复制得到的数组的元素都改变。

  1. 深层复制(Deep Copy)
    当我们复制对象数组时,因为每个对象实例都有各自的属性,用户需要手动将所要复制的对象属性指定到新建的数组中。
class Clothes{//定义一个对象,实例化元素添加到数组    String color;    char size;    Clothes(String color,char size){        this.color = color;        this.size = size;    }}public class DeepCopy{    public static void main(String[] args){        Clothes[] c1 = {new Clothes("red",'L'),new Clothes("blue",'M')};        Clothes[] c2 = new Clothes[c1.length];        for(int i = 0;i<c1.length; i++){            Clothers c = new Clothes(c1[i].color, ci[i].size);            c2[i] = c;            }        c1[0].color = "yellow";        System.out.println(c2[0].color);    }}

3.字符串对象

字符串本质上是打包字符数组的对象,是java.lang.String类的实例。
由于字符串在Java中是对象,所以也就拥有一些可操作的方法,像是可以使用length()方法取得字符串长度,使用charAt()取得字符串指定从0开始索引的某个字符,使用toUppercase()将原本为小写的字符串转换成大写。
如果要将字符串转换成整数、浮点数等基本类型,可以使用一下剖析方法:

方法 说明 Byte.parseByte(num) 将字符串num剖析成byte类型整数 Short.parseShort(num) 将字符串num剖析成short类型整数 Integer.parseInt(num) 将字符串num剖析成int类型整数 Long.parseLong(num) 将字符串num剖析成long类型整数 Float.parseFloat(num) 将字符串num剖析成float类型浮点数 Double.parseDouble(num) 将字符串num剖析成double类型浮点数

4.字符串特性

  • 字符串池与字符串常量:
String name1 = "麦克喵";//字符串常量String name2 = "麦克喵";String name1 = new String("麦克喵");//字符串池String name1 = new String("麦克喵");name1 = name2; //truename1 = name3; //falstname3 = name4; //falst

在Java中,为了效率考虑,以“”包括的字符串只要内容相同,无论在程序代码中出现多少次,JVM都只会建立一个Integer实例,并在字符串池中维护,直到GC清除。
即引用一个类型时,看是否创建出一个新的实例,这也是一直在强调的,只是比较实质内容的情况,尽量使用equals()方法。

  • 不可变动字符串
    在Java中,字符串对象一旦建立,就无法更改对象中的内容,而使用+连接字符串的情况,实质上是建立了一个java.lang.StringBuilder对象,它使用append()对+左右的字符串进行连接,并通过toString()方法返回String类型。
    java.lang.StringBuilder是JDK1.5之后新增的类,在该版本之前,是使用java.lang.StringBuffer类,StringBuilder与StringBuffer具有相同的操作接口,在单机非多线程(Multithread)的情况下,使用StringBuilder会有较好的效率,因为StringBuilder不会处理同步(Synchronized)的问题。

     
     

参考文章:
1.关于float类型的剖析
2. 关于 Java 数组的 12 个最佳方法
3.String、StringBuffer与StringBuilder之间区别