1 静态导入
2 增强for循环
3 可变参数
4 自动装箱与自动拆箱
5 枚举
1 静态导入
静态导入的作用:简化书写。
静态导入可以作用于一个类的所用静态成员。
静态导入的格式:
import static 包名.类名.静态的成员;
静态导入要注意的事项:
- 如果静态导入的成员与本类的静态成员存在同名的情况下,那么默认使用本类的静态成员;如果需要指定使用静态导入的成员,那么需要在静态成员前面加上类名。
import static java.util.Collections.sort;
import static java.util.Collections.binarySearch;
import static java.util.Collections.max;
//import static java.util.Collections.*;
import static java.lang.System.out;
public class Demo1 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(13);
list.add(9);
list.add(10);
list.add(19);
// sort(list); 此时就会调用本类的方法
Collections.sort(list);
out.println("集合中的元素:" + list);
out.println(binarySearch(list, 13));
out.println(max(list));
}
public static void sort(ArrayList<Integer> list) {
System.out.println("本类的成员..");
}
}
2 增强for循环
增强for循环的作用:简化迭代器的书写格式。(注意:增强for循环的底层还是使用了迭代器遍历)
增强for循环的适用范围:如果是实现了Iterable接口(单列集合的跟接口Collection继承了Iterable接口)的对象或者是数组对象都可以使用增强for循环。
增强for循环要注意的事项:
- 增强for循环底层也是使用了迭代器获取的,只不过获取迭代器由jvm完成,不需要我们获取迭代器而已,所以在使用增强for循环遍历元素的过程中不准使用集合对象对集合的元素个数进行修改。
- 迭代器遍历元素与增强for循环遍历元素的区别:使用迭代器遍历集合的元素时可以使用迭代器对象删除(remove)集合的元素;而增强for循环遍历集合的元素时,不能调用迭代器的remove方法删除元素。
- 普通for循环与增强for循环的区别:普通for循环可以没有遍历的目标,而增强for循环一定要有遍历的目标。
public class Demo2 {
public static void main(String[] args) {
HashSet<String> set = new HashSet<String>();
set.add("狗娃");
set.add("狗剩");
set.add("铁蛋");
// 使用迭代器遍历集合元素
Iterator<String> it = set.iterator();
while(it.hasNext()) {
String temp = it.next();
System.out.println("元素:" + temp);
}
// 使用增强for循环实现
for(String item : set) {
System.out.println("元素:" + item);
}
int[] arr = {12,5,6,1};
// 使用for循环遍历
for(int i = 0; i < arr.length; i ++) {
System.out.println("元素:" + arr[i]);
}
// 使用增强for循环实现
for(int item : arr) {
System.out.println("元素:" + item);
}
// 需求:在控制台上打印出5句hello world
for(int i = 0; i < 5; i ++) {
System.out.println("hello world");
}
// 如果要使用增强for循环实现这个需求的话,会很麻烦(没有遍历的目标)
// 注意:Map集合没有实现Iterable接口,所以Map集合不能直接使用增强for循环。如果需要使用增强for循环,需要借助于Collection集合。
HashMap<String,String> map = new HashMap<String,String>();
map.put("001", "张三");
map.put("002", "李四");
map.put("003", "王五");
map.put("004", "赵六");
Set<Map.Entry<String, String>> entrys = map.entrySet();
for(Map.Entry<String, String> entry : entrys) {
System.out.println("键:" + entry.getKey() + ",值:" + entry.getValue());
}
}
}
3 可变参数
需求:定义一个函数做加法功能。(函数做几个数据的加法,这一点是不确定的)
public class Demo4 {
public static void main(String[] args) {
int[] arr = {2,42,5,6,7};
add(arr);
}
public static void add(int[] arr) {
int result = 0;
for(int item : arr) {
result += item;
}
System.out.println(result);
}
}
可变参数要注意的细节:
- 如果一个函数的形参使用上了可变参数之后,那么调用该方法的时候可以传递参数也可以不传递参数。
- 可变参数实际上是一个数组对象。调用方法时jvm会将传入的实参存放在一个数组中,之后将这个数组中的内容传递给可变参数。调用方法不传递参数时,可变参数的长度为0,不会出现空指针异常。
- 可变参数必须位于形参中的最后一个参数。
- 一个函数最多只能有一个可变参数,因为可变参数必须位于形参中的最后一个位置上。
public class Demo4 {
public static void main(String[] args) {
add(2,42,5,6,7);
}
public static void add(int... arr) {
int result = 0;
for(int item : arr) {
result += item;
}
System.out.println(result);
}
}
4 自动装箱与自动拆箱
java是面向对象的语言,任何事物都可以使用类进行描述,sun就使用了一些类描述java中的八种基本数据类型。
基本数据类型 包装类型
byte Byte
short Short
int Integer
long Long
float Float
double Double
boolean Boolean
char Character
基本数据类型有了对应的包装类型的好处:
public class Demo5 {
public static void main(String[] args) {
String str = "12";
// 把字符串转成int类型的数据。可以把字符串转换成对应的数字
int i = Integer.parseInt(str);
System.out.println(i);
// 把数字转换成字符串
System.out.println("把整数转换成对应的字符串:" + Integer.toString(i));
// 把整数转换成对应的进制形式
System.out.println("10的二进制:" + Integer.toBinaryString(10)); // 1010
System.out.println("10的八进制:" + Integer.toOctalString(10)); // 12
System.out.println("10的十六进制:" + Integer.toHexString(10)); // a
// 可以把字符串当成对应的进制数据帮你转换
String data = "10";
int a = Integer.parseInt(data, 2); // 把字符串当成二进制转换成十进制。
System.out.println("a = " + a); // a = 2
// 集合是可以存储任意对象类型数据的容器
ArrayList list = new ArrayList();
list.add(1);
list.add(3);
list.add(17);
// 为什么集合又能存储基本数据类型了?因为JDK1.5出现了自动装箱
// 自动装箱:自动把java的基本数据类型数据转换成对象类型数据。
int temp = 10;
Integer b = temp; // 把temp存储的值赋值给b。
// Integer b = new Integer(temp); JDK1.5之前就要这样写,否则报错。
// 自动拆箱:把引用类型的数据转换成基本类型的数据
Integer c = new Integer(13);
int d = c;
// int d = c.intValue(); JDK1.5之前就要这样写,否则报错。
System.out.println(d);
// 引用的数据类型
Integer e = 127;
Integer f = 127; // -128~127之间为true,超出这个范围就为false。
System.out.println("是同一个对象吗?" + (e == f)); // Integer内部维护了一个缓冲数组,该缓冲数组中存储了-128~127这些数据,如果你获取的数据是在这个范围之内的,那么就直接从缓冲区中获取;如果超过这个范围,就会创建新的对象。
}
}
5 枚举
class Person {
String name;
String sex;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setSex(String sex) {
if("男".equals(sex)) {
this.sex = sex;
}else if("女".equals(sex)) {
this.sex = sex;
}else {
throw new RuntimeException("垃圾数据...");
}
}
public String getSex() {
return sex;
}
}
public class Demo6 {
public static void main(String[] args) {
Person p = new Person();
p.setName("狗娃");
p.setSex("人妖");
System.out.println("名字:" + p.getName() + ",性别:" + p.getSex());
}
}
缺点:当传入的实参不是"男"和"女"时,编译不会报错,运行时报错。
问题:某些方法所接收的数据必须是在固定的范围之内的。
解决方案:这时候我们的解决方案就是自定义一个类,然后私有化构造方法,在自定义类中创建本类的对象对外使用。
/**
* 自定义一个性别类
*/
class Gender {
String value;
// 提供两个本类的最终的常量给外界使用
public static final Gender man = new Gender("男");
public static final Gender woman = new Gender("女");
private Gender(String value) {
this.value = value;
}
}
class Person {
String name;
Gender sex; // 声明一个自定义类的数据类型变量
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Gender getSex() {
return sex; // 返回的其实是new Gender("男")对象的内存地址
}
public void setSex(Gender sex) { // 只接收Gender类型的数据(对象)
this.sex = sex;
}
}
public class Demo6 {
public static void main(String[] args) {
Person p = new Person();
p.setName("狗娃");
p.setSex(Gender.man); // Gender类的构造方法是私有的,所以不能创建Gender对象,只能使用Gender类的常量
System.out.println("名字:" + p.getName() + ",性别:" + p.getSex().value); // 名字:狗娃,性别:男
}
}
JDK1.5对以上问题提出了新的解决方案:使用枚举类解决。
一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,Java5以后可以直接使用枚举予以解决。
枚举要注意的细节:
- 枚举类也是一个特殊的类
- 枚举值默认的修饰符是public static final
- 枚举值的数据类型是枚举值所属的类(枚举类)的数据类型,枚举值是指向了本类的对象的
- 枚举类的构造方法默认的修饰符是private
- 枚举类可以定义自己的成员变量和成员函数
enum Sex {
man, woman; // 枚举值 这里调用了无参的构造方法
/*
就相当于:
public static final Sex man = new Sex();
public static final Sex woman = new Sex();
*/
String value; // 成员变量
// 成员函数
public void getValue() {
System.out.println("value:" + value);
}
}
public class Demo7 {
public static void main(String[] args) {
// 获取枚举类的对象
Sex sex = Sex.man;
sex.value = "男";
sex.getValue(); // value:男
}
}
枚举要注意的细节:
- 枚举值可以自定义构造函数,但构造函数的修饰符必须是private。如果是有参的构造函数,枚举值必须要传入实参
- 枚举类可以存在抽象的方法。当存在抽象方法时,枚举值就必须实现抽象的方法
- 枚举值必须要位于枚举类的第一个语句,否则报错
enum Sex1 {
man("男") {
@Override
public void run() {
System.out.println("男人在跑...");
}
}, woman("女") {
@Override
public void run() {
System.out.println("女人在跑...");
}
}; // 枚举值
private Sex1(String value) { // 自定义有参的构造方法
this.value = value;
}
String value; // 成员变量
// 成员函数
public void getValue() {
System.out.println("value:" + value);
}
// 抽象的方法
public abstract void run();
}
public class Demo8 {
public static void main(String[] args) {
Sex1 sex = Sex1.man;
sex.getValue(); // value:男
sex.run(); // 男人在跑
}
}
枚举类的引用:
一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,Java5以后可以直接使用枚举予以解决。比如:方向、性别、季节、星期…
//自定义一个性别类
/*
class Gender {
String value;
// 提供两个本类的最终的常量给外界使用
public static final Gender man = new Gender("男");
public static final Gender woman = new Gender("女");
private Gender(String value) {
this.value = value;
}
}
*/
/**
* 用枚举类代替上述自定义的性别类
*/
enum Gender {
man("男"), woman("女");
String value;
private Gender(String value) {
this.value = value;
}
}
class Person {
String name;
Gender sex; // 声明一个枚举类的数据类型变量
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Gender getSex() {
return sex;
}
public void setSex(Gender sex) {
this.sex = sex;
}
}
public class Demo6 {
public static void main(String[] args) {
Person p = new Person();
p.setName("狗娃");
p.setSex(Gender.man);
System.out.println("名字:" + p.getName() + ",性别:" + p.getSex().value); // 名字:狗娃,性别:男
}
}
switch语句适用的数据类型:byte \ char \ short \ int \ String \ 枚举类型
注意:case语句后面跟的枚举值,只需要单写枚举值即可,不需要声明该枚举值是属于哪个枚举类的。
enum Season {
spring, summer, autumn, winter;
}
public class Demo9 {
public static void main(String[] args) {
Season season = Season.winter;
switch(season) {
case spring: // Season.spring 这样写会报错
System.out.println("春天...");
break;
case summer:
System.out.println("夏天...");
break;
case autumn:
System.out.println("秋天...");
break;
case winter:
System.out.println("冬天...");
break;
}
}
}