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

一、类 型

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
字符型 booleanBoolean 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,大于返回1
Number num = 2.71828f;//使用一般化Number类
Integer i = 10;
System.out.println(i+10);//i会自动拆箱进行加法运算输出20
System.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; //true
name1 = name3; //falst
name3 = 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之间区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值