变量的基本原理
变量是程序的基本组成单位
变量表示内存中 的一个存储区域
变量有三个基本要素(类型+名称+值)
变量使用的步骤
- 声明变量int a;
- 赋值a=3;
- 使用System.out.println(a);
程序中+的使用
- 左右两边都是数值型时,则作加法运算
- 左右两边有一个为字符串,则作拼接运算
System.out.println(“heeo"+110);输出heeo110
数据类型
基本数据类型
数值型
整数类型
- short(2)
- byte(1字节)
- int (4)
- long (8)
整型细节
- 整型常量默认为int型,声明long型需要在后面加“l”或"L"
- 字节大的数据类型转换为字节小的数据类型可能会造成数据损失
- 尽量使用小的数据类型,必要是才用long
- 计算机中的最小存储单位是bit .1byte=8bits;
浮点类型
- float
- double
浮点型细节
1.浮点数=符号位+指数位+尾数位
2. 尾数部分可能丢失,造成精度损失(小数都是近似值)
3. 浮点型常量默认为double型,声明float需要后缀“f"或”F“
4. 浮点型常量有两种表示方法:十进制和科学计数法,科学计数法例如5.12e4
5. 通常使用double,double更精准
6. 浮点数计算是取近似值,当我们对运算是小数的进行相等判断时,要小心,应该是以两个数的差值的绝对值在某个精度范围内判断
7. 直接赋值的两个数可以判断相等
字符型 char(2)
字符型使用
- 字符类型可以直接存放一个数字,输出数字表示的字符(Unicode码)
- 字符常量用单引号括起来
- 转义符最后输出转义符代表的字符常量
- [[Unicode]]
- char类型是可以进行运算的,相当于一个整数(Unicode码)
- char c=99;
System.out.println©;//输出99对应的ASII字符 - char b=3889;
System.out.println(b);//输出“韩”;
字符类型本质
存储:‘a’–>码值97–>二进制(1100001)–>存储
读取:二进制(1100001)–>97–>'a’–>显示
字符编码
- ASII:用一个字节表示,一共128个字符;实际上一个直接可以表示256个字符
- Unicode :使用两个字节表示,在ASII基础上扩展,字母和汉字用两个字节表示;
- utf-8:比Unicode更灵活,字母一个字节,汉字三个字节;
- gbk:字母一个字节,汉字两个字节(表示的汉字不如utf-8多);
- big5:可以存放繁体中文;
布尔型 boolean(1)
JAVA布尔类型只能是true或false,不能是1或0
主要适用于逻辑运算;
基本数据类型转换
自动类型转换
从低精度向高精度转换;
把一个具体的数赋给byte时,如果该数在byte范围内,就可以;如果是变量赋值,就要判断类型;
byte n1=10;(正确)
int n2=20;
byte b2=n2;(错误)
自动转换细节:
- 有多种类型的数据混合运算时,首先自动将所有数据转化成容量最大的那种数据类型,然后进行运算;
- 把精度大的数据类型转换为精度小的数据类型时,会报错
- (byte,short)和char 类型之间不会自动转换
- byte,short ,char 之间可以计算,计算时首先转化为int 类型
byte b1=1;byte b2=2;
byte b3=b1+b2;//错误,b1+b2是int类型,int赋值byte出错; - boolean不参与转换
- 表达式的结果的类型自动提升为操作数中的最大的数据类型
强制类型转换
会造成精度消失或数据溢出;
细节
- 大->小,需要强制类型转换
- 强转符号只对最近的操作数有效,往往会使用小括号提升优先级
(int)3*4.4;//其实只强转 了3; - char类型可以保存int类型常量但不能保存变量需要强转;
- byte和short类型在运算时当作int类型处理;
基本数据类型和String类型转换
基本数据类型–>String
基本数据类型+”“
String–>基本数据类型
parseInt:
String s5=“123”;
int num1=Interger.parseInt(s5);
类似还有:Double.parseDouble(s5);Float.parseFloat(s5),Long.parseLong(s5);Byte.parseByte(s5);Boolean.parseBoolean(“true”);Short.parseShort(s5);
细节
String 类型转换为基本数据类型时,要确保String类型可以被转换为有效数据,eg:"13"可以转换为整数,但“abc"不能转换为整数。
如果格式不正确会抛出‘[[异常]],程序会终止。
引用数据类型
类
接口
数组
包装类型:
均继承自Number抽象类,把基本数据类型封装成为对象。基本类型和包装类型之间会自动进行转化;
-
基本类型(如int),是一个值。允许不赋初值,系统自动添加默认值。
-
包装类型(如Integer),是一个对象。实例化必须赋初值,且赋值后不能改变(final)。
数组
Array类
数组:数据的集合,本质是一个对象,数据存储在堆区,由引用指向数组首个元素的地址。
Arrays 类
对数组进行操作的辅助类,实现对数组的常用操作;
sort方法
Arrays.sort(arr);
copyOf/copyOfRange 方法
int[] arr1 = Arrays.copyOf(arr, 10); // 复制数组:前 10 个单位
int[] arr2 = Arrays.copyOf(arr, 0, arr.length); // 复制数组:从 0 到 arr.length - 1//左闭右开!
asList方法
将数组转换为列表(List),但数组数据必须时包装类型;
调用该方法将数组转换为列表后,在内存中实际还是以数组形式存储。这可能会导致以下两个问题:
- 调用 List 类的 add 方法向列表中插入数据,会导致异常;
- 对原数组进行更改,也会导致列表中的数据发生变化。
arr[] = new Integer[]{1, 2, 3, 4}; // 数组必须是包装数据类型
List list = Arrays.asList(arr); // 将数组转换为集合(有问题)
List list = new ArrayList<>(Arrays.asList(arr)); // 将数组转换为集合(推荐)
字符串
String类
创建字符串
-
直接赋值:如果常量池没有,则在常量池新建对象。否则直接使用常量池中已有对象,引用指向常量池。
-
构造方法:如果常量池没有,则在常量池新建对象。无论如何一定会在堆区创建对象,引用指向堆区。
String str1 = "string"; // 引用指向常量池
String str2 = "str" + "ing"; // 引用指向常量池(指向 str1 的字符串对象)
String str3 = new String("string"); // 引用指向堆区(在堆区新建字符串对象)
String str4 = str1 + str2; // 引用指向堆区
String newStr = new String(str.getBytes("ISO-8859-1"), "GBK"); // 获取指定类型编码对象,按指定类型编码
常用方法
int len = str.length(); // 返回字符串长度
String[] strs = str.split(","); // 按分隔符分解字符串
boolean c = str.contains(str2); // 判断是否存在子字符串
int index = str.indexOf(str2); // 查找子字符串出现的第一个位置,没有返回-1
int index = str.lastIndexOf(str2); // 查找子字符串出现的最后一个位置,没有返回-1
String str2 = str.trim(); // 去除字符串左右空格
String str2 = str.substring(0,3); // 截取指定位置(0-2)的子字符串
String str2 = str.replace("a", "b"); // 新字符 a 替换旧字符 b
类型转换
// Number > String
String s1 = data.toString(); // data 必须为包装数据类型
String s2 = Integer.toString(data); // data 可以为基础数据类型,包括字符数组 char[]
String s3 = String.valueOf(data); // data 可以为基础数据类型,包括字符数组 char[]
// String > char
char c = str.charAt(0);
char[] ch = str.toCharArray();
// String > int
int n1 = Integer.parseInt(str);
int n2 = Integer.valueOf(str);
StringBuilder/StringBuffer类
由于 String 类不可变性,对其频繁更改往往会产生较多临时变量类,占用大量内存。对此我们通常使用 StringBuilder/StringBuffer 来避免,这两个类允许在原有内存地址对字符串进行操作。其中 StringBuilder 类性能更好,StringBuffer 类线程安全。
StringBuffer str = new StringBuffer("hello");//字符串默认长度为16,超出后扩容
//StringBuffer/StringBuilder 类转换成String类
String str2 = str.toString();
专用方法
str.append("add"); // 末尾添加字符串,也可以是其他基础类型
str.insert(0,"insert"); // 指定位置插入字符串,也可以是其他基础类型
str.deleteCharAt(6); // 删除指定位置(6)的字符
str.delete(6,8); // 删除指定位置(6和7)的字符串
str.reverse(str2); // 翻转字符串
大数
BigInteger 类
主要用来操作比 long 类型更大的整型数字。
BigDecimal 类
基于 BigInteger 类实现。由于基本浮点数类型(float/double) 会产生精度丢失问题,因此常使用 BigDecimal 类代替。涉及金额必须使用该类。
枚举
自定义枚举类实际是继承 Enum 类的 final 类,在类中将自定义该类型的 public static final 属性,并引入了相关方法。
// 定义枚举类
public enum Day {
MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
// 使用枚举类
public class Demo {
public boolean test(Day today){
if(today == Day.MONDAY) return true;
else teturn false;
}
}
时间
在日常 Java 开发中,我们最常使用 Long 类型,而不是 Date/Timestamp 类型表示时间。
我们可以通过 System.currentTimeMillis 方法获取当前系统时间,默认为 13 位的数字(精确到 ms)
Long timestamp1 = System.currentTimeMillis(); // 13 位 精确到 ms
Long timestamp2 = (System.currentTimeMillis()) / 1000; // 10 位 精确到 s
泛型
定义类时并不固定数据类型,等到创建对象或调用方法时再明确数据类型。