枚举类型
- 如果一个变量的取值只可能是固定的几个值,可以考虑使用枚举类型;
public enum Season {
SPRING,SUMMER,FALL,WINTER
}
import com.example.java_test.java.cls.Season;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Season season = Season.SPRING;
Log.v("MainActivity",season.name());
Log.v("MainActivity",String.valueOf(season.ordinal()));
switch (season) {
case SPRING:
Log.v("MainActivity","春天");
break;
case SUMMER:
Log.v("MainActivity","夏天");
break;
case FALL:
Log.v("MainActivity","秋天");
break;
case WINTER:
Log.v("MainActivity","冬天");
break;
}
}
}
- 枚举的本质是类,所有枚举类型最终都隐式继承自
java.lang.Enum
;
- 枚举定义完常量后,可以再定义成员变量,方法等内容(这时最后一个常量要以分号结束);
- 枚举的构造方法权限必须是无修饰符 或者 private
- Java会主动调用构造方法初始化每一个常量,你不能主动调用构造方法;
public enum Season {
SPRING,SUMMER,FALL,WINTER;
private int age;
private String str;
Season() {
}
void test() {
}
}
自定义构造方法的枚举
public enum Season {
SPING(5,15),
SUMMER(5,15),
FALL(5,15),
WINTER(5,15);
//温度
private int min;
private int max;
//自定义构造方法 私有
Season(int min,int max) {
this.min = min;
this.max = max;
}
public int getMin() {
return min;
}
public int getMax() {
return max;
}
}
基本数据类型的缺陷
- 对比引用类型,基本数据类型存在一些缺陷;
- 无法表示不存在的值(null值);
- 不能利用面向对象的方式去操作基本数据类型,比如直接调用基本数据类型调用方法;
- 当方法参数是引用类型时,基本类型无法传递;
- 解决方案:可以自己将基本数据类型包装成引用类型;
- 案例:自定义包装int的类
IntObject
public class IntObject {
public int value;
public IntObject(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
包装类
- 在Java中已经内置了基本数据类型的包装类,都在java.lang包中;
- 其中数字类型的包装类最终都继承自java.lang.Number
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Integer num2 = Integer.valueOf(100);
Integer num3 = new Integer(100);
}
}
自动装箱,拆箱
- 自动装箱:Java编译器会自动调用xxx.vauleOf方法,将基本数据类型转换成包装类;
- 自动拆箱:Java编译器会自动调用xxxValue方法,将包装类转换为基本类型;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//自动装箱 将100 自动转成 Integer
Integer num1 = 100;
Integer num2 = Integer.valueOf(100);
Integer num3 = new Integer(100);
//自动拆箱 将Integer 自动转成 int
int num4 = num1;
}
}
包装类的判等
- 使用
equals
:判断的是引用所指向的内容是否相等;
- 使用
==
:判断的是引用的值,即所指向的对象的内存地址是否相等;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Integer num1 = 100;
Integer num2 = 100;
Integer num3 = 888;
Integer num4 = 888;
//不推荐
System.out.println(num1 == num2); //true
System.out.println(num3 == num4); //false
//推荐
System.out.println(num1.equals(num2)); //true
System.out.println(num3.equals(num4)); //true
}
}
System.out.println(num3 == num4)
返回false,主要是因为 Integer内部有个缓存IntegerCache
,当数字在(-127,128)之间的Integer会被IntegerCache
缓存下来,所以num1 = 88会被缓存下来,num2直接从缓存中取出,num3 =888,超出范围不会缓存;
基本类型数组
与包装类数组
之间是不能自动装箱,拆箱的;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int[] num1 = {11,22};
Integer[] num2 = num1; //报错
}
}
Math
- java.lang.Math类提供了常见的数学计算功能;
public static final double E = 2.7182818284590452354;
public static final double PI = 3.14159265358979323846;
//绝对值
Math.abs(-100);
//最大值
Math.max(100,200);
//最小值
Math.min(100,200);
//4的2次方
Math.pow(4,2);
//向下取整
Math.floor(3.2);
//向上取整
Math.ceil(3.7);
//16的平方根
Math.sqrt(16);
//E的2次方
Math.exp(2);
//ln8
Math.log(8);
//角度转弧度
double degree = 90;
double radian = Math.toDegrees(degree);
//三角函数
Math.sin(radian);
Math.tan(radian);
//生成[0-1)之间的随机数
Math.random();
//生成各种随机数
Random r = new Random();
r.nextBoolean();
r.nextInt();
r.nextLong();
r.nextFloat();
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//生成[0,99]的整数
int num1 = (int)(Math.random() * 100);
int num2 = new Random().nextInt(100);
//生成[10,99]的整数
int num3 = (int)(Math.random() * 90) + 10;
int num4 = new Random().nextInt(90) + 10;
}
}
import java.util.Random;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//随机生成4维大写字母 A-Z ==> A + [0,25]
for (int i = 0;i < 4;i++) {
int c = 'A' + new Random().nextInt(26);
System.out.println("MainActivity" + (char)c);
}
}
}
UUID
- UUID:通用唯一标识符;
- 其目的是让分布式系统中所有元素都能有唯一的标识符,而不需要通过中央控制端来做标识符的指定;
- 可以利用java.lang.UUID 类的randomUUID方法生成一个128bit的随机UUID;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("MainActivity" + UUID.randomUUID());
}
}
数字格式化
- 可以使用System.out.printf或者System.out.format输出格式化的字符串;
- 可以使用String.format创建格式化的字符串;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.printf("my age is %d",10);
String str = String.format("my age is %d",20);
long n = 461012;
System.out.format("%d%n",n); //"461012"
System.out.format("%08d%n",n); //"00461012"
System.out.format("%+8d%n",n); //" +461012"
System.out.format("%,8d%n",n); //" 461,012"
System.out.format("%+,8d%n%n",n); //"+461,012"
double pi = Math.PI;
System.out.format("%f%n",pi); //"3.141593"
System.out.format("%03f%n",pi); //"3.142"
System.out.format("%8.3f%n",pi); //" 3.142"
System.out.format("%08.3f%n",pi); //"0003.142"
System.out.format("%-8.3ff%n",pi); //"3.142"
}
}
DecimalFormat
- 使用java.text.DecimalFormat可以更好的控制前0,后0,前缀,后缀,分组分隔符,十进制分隔符等;
import java.text.DecimalFormat;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//123,456.789
customFormat("###,###.###",123456.789);
//123456.79
customFormat("###.##",123456.789);
//00123.780
customFormat("000000.000",123.78);
//$12,345.67
customFormat("$###,###.###",12345.67);
}
public static void customFormat(String pattern,double value) {
DecimalFormat format = new DecimalFormat(pattern);
System.out.println(format.format(value));
}
}
字符串转数字
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Integer num1 = Integer.valueOf("12");
int num2 = Integer.parseInt("12");
int num3 = Integer.parseInt("FF",16);
Float f1 = Float.valueOf("12.34");
float f2 = Float.parseFloat("12.34");
}
}
数字转字符串
- 使用字符串的valueOf方法,包装类的toString方法;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String str1 = String.valueOf(12.34);
String str2 = Integer.toString(255);
String str3 = Integer.toString(255,16);
String str4 = Float.toString(12.34f);
}
}
高精度计算
- float,double存储的只是小数的近似值,并非精确值,因此不适合用来进行高精度计算;
- 建议使用字符串初始化
BigDecimal
,因为float,double存储的是近似值,不是精确值;
import java.math.BigDecimal;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//不推荐
float f = 0.7f;
double d = 0.7f;
System.out.println(0.7 * 0.7);
//推荐做法
BigDecimal d1 = new BigDecimal("0.7");
BigDecimal d2 = new BigDecimal("0.7");
System.out.println(d1.add(d2)); //加
System.out.println(d1.subtract(d2)); //减
System.out.println(d1.multiply(d2)); //乘
System.out.println(d1.divide(d2)); //除
System.out.println(d1.setScale(3)); //保留3位小数
}
}
字符串
- Java中用java.lang.String类代表字符串;
- 底层使用char[] 存储字符数据,从Java9开始底层使用byte[] 存储字符数据;
- 所有字符串的字面量(比如"abc"),都是String类的实例;
- String对象一旦创建完毕,它的字符内容是不可以修改的;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String s = "555";
s += "555";
s = "666";
test(s);
System.out.println(s);
}
public static void test(String str) {
str += "555";
}
}
- 字符串的引用指向可以更改,但字符串本身的内容值不能更改;
字符串常量池(String Contant Pool)
- Java中有个字符串常量池,简称SCP;
- 从Java7开始属于堆空间的一部分,以前放在方法区;
- 当遇到字符串字面量时,会去查看字符串常量池;
- 如果字符串常量池中存在与字面量内容一样的字符串对象A时,就返回A;
- 否则,创建一个新的字符串对象D,并加入到字符串常量池中,返回D;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String str1 = "yanzi";
String str2 = "yanzi";
System.out.println(str1 == str2); //true
String s1 = "mj";
String s2 = new String("mj");
String s3 = new String(s2);
String s4 = new String(s2);
char[] cs = {'m','j'};
String s5 = new String(cs);
String s6 = new String(s5);
}
}
- str1的字面量存入字符串常量池SCP中,
- str2直接从SCP中取出,所以str1与str2指向的是同一个对象;
-
String s1 = "mj"
,直接将字面量mj
存储SCP中;
-
String s2 = new String("mj")
:创建一个新的字符串对象,其内容指向SCP中的mj;
-
char[] cs = {'m','j'}
:创建一个char数组,存储了mj;
-
String s5 = new String(cs)
:会拷贝新的一份char数组;
intern方法
- A.intern方法的作用:
- 如果SCP中存在与A内容一样的字符串对象C时,就返回C;
- 否则,将A加入到SCP中,返回A;
public class Main {
public static void main(String[] args) {
int a = 1,b = 2,c = 3;
String s1 = String.format("%d%d%d", a,b,c);
String s2 = String.format("%d%d%d", a,b,c);
String s3 = s1.intern();
String s4 = s2.intern();
String s5 = "123";
System.out.println(s1 == s2);//false
System.out.println(s1 == s3);//true
System.out.println(s1 == s4);//true
System.out.println(s1 == s5);//true
}
}
-
String s1 = String.format("%d%d%d", a,b,c)
:会创建新的字符串对象,所以s1与s2是两个字符串对象;
-
String s3 = s1.intern()
:会先去SCP中查找字符串abc,此时SCP中没有abc,那么会将abc放入SCP中;
-
String s4 = s2.intern()
:会先去SCP中查找字符串abc,此时SCP中存在abc,所以s3与s4指向的是同一个字符串对象;
-
String s5 = "123"
:也会先去SCP中查找字符串abc,与intern的执行逻辑等价,所以s1,s3,s4,s5都指向的是同一个字符串对象;
- 断点调试结果如下:
字符串的常用方法
import javax.swing.AbstractCellEditor;
public class Main {
public static void main(String[] args) {
//去除左右空格: "123 3456"
String str1 = " 123 3456 ".trim();
//转为大写: "ABC"
String str2 = "abc".toUpperCase();
//转为小写: "abc"
String str3 = "ABC".toLowerCase();
//是否包含某个字符串:true
boolean isContains = "123456".contains("23");
//是否以某个字符串开头:true
boolean isStart = "123456".startsWith("1");
//是否以某个字符串结尾:true
boolean isEnd = "123456".endsWith("6");
//将字符串分割为数组:[1,2,3,4]
String[] strs = "1_2_3_4".split("_");
//字符串比较大小: < 0
int result1 = "abc".compareTo("bbb");
//字符串比较大小,忽略大小写: < 0
int result2 = "abc".compareToIgnoreCase("ASS");
//比较字符串内容是否相等
String s1 = "abc";
String s2 = new String("abc");
s1.equals(s2);
//比较字符串内容是否相等 忽略大小写
"asd".equalsIgnoreCase("ASd");
//字符串截取左闭右开[beginIndex,endIndex): 123
String s3 = "yanzi123dd".substring(5,8);
System.out.println(s3);
//返回字符索引 从左到右
int index1 = "12355".indexOf(2);
//返回字符索引 从右到左
int index2 = "asdfasf44trtr".lastIndexOf(4);
}
}
StringBuilder