版权声明:本文为 小异常 原创文章,非商用自由转载-保持署名-注明出处,谢谢!
本文网址:https://blog.csdn.net/sun8112133/article/details/89133616
一、自动装箱、拆箱
1、自动装箱、拆箱概述
自动装箱、拆箱指的是Java中基本数据类型与其对应的引用类型的自动转换。分别对应以下:
byte → Byte
short → Short
char → Character
int → Integer
long → Long
float → Float
double → Double
boolean → Boolean
2、自动装箱、拆箱好处
代码简洁,不容易出错。
3、使用方式
1)自动装箱
基本数据类型自动转为包装类型(如:int --> Integer)。
2)自动拆箱
包装类自动转为基本类型(如:Integer --> int)。
4、注意事项
在遍历的过程中,不能对集合或数组中的元素进行增删改操作。
5、应用
1)自动装箱
Integer i = 10; // 相当于 Integer i = new Integer(10);
2)自动拆箱
Integer i = 10;
int a = i; // 相当于 int a = i.intValue();
二、增强For循环
1、增强For循环概述
增强For循环是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个迭代器,所以在遍历的过程中,不能对集合中的元素进行增删改操作。
2、增强For循环的好处
代码简洁,不容易出错,不用考虑集合中的下标。
3、使用方式(语法格式)
for (元素类型 变量名 : 集合/数组) {
// 可以直接使用变量
}
4、注意事项
在遍历的过程中,不能对集合或数组中的元素进行增删改操作。
5、应用场景
List<String> list = new ArrayList<>;
list.add("hello");
list.add("world");
for (String s : list) {
System.out.println(s);
}
三、可变参数
1、可变参数概述
可以变化的参数。它其实就是一个数组。
2、可变参数好处
1)定义方法的时候不知道该定义多少个参数。
2)参数类型相同时,把重载方法合并到了一起。
3、使用方式(语法格式)
[修饰符] 返回值类型 方法名(数据类型... 变量名)
4、注意事项
1)这里的变量其实是一个数组。
2)如果一个方法有可变参数,并且有多个参数,那么可变参数必须是最后一个。
5、应用场景
public static void main(String[] args) {
int sum = sum("sum: ",1,2); // 3
sum = sum("sum: ",1,2,3); // 6
sum = sum("sum: "); // 0
System.out.println("sum: " + sum);
}
四、静态导入
1、静态导入概述
静态导入是导入类中的静态成员。如果有多个同名的静态成员,容易产生冲突,所以在开发中一般不用。
2、静态导入好处
可以直接在类中使用导入后的静态成员,不需要再加类名前缀。
3、使用方式(语法格式)
import static 包名.类名.静态成员名;
4、注意事项
成员必须是静态的。
5、应用场景
import static java.lang.Math.PI;
import static java.lang.Math.abs;
public class Demo {
public static void main(String[] args) {
System.out.println("PI: " + PI); // PI: 3.141592653589793
System.out.println("-5的绝对值:" + abs(-5)); // -5的绝对值:5
}
}
五、枚举
1、枚举概述
是指将变量的值一一列出来,变量的值是有限个的。(举例:一周只有7天,一年只有12个月等。)当枚举只有一个成员时,则可以作为一种单例模式的实现方式。
枚举类在编译后,实际上是转化为一个继承了 java.lang.Enum类 的实体类。
2、枚举好处
简洁明了。
3、常用方法
int ordinal()
获取当前枚举项的编号(从0开始)。
int compareTo(E e)
比较当前枚举项与指定枚举项的编号(当前枚举项 - 指定枚举项)
String name()
获取当前枚举项的名称。
T valueOf(String name)
通过枚举项名获取枚举项。
values()
JDK文档没有,遍历枚举类中的所有枚举项。
4、注意事项
1)定义枚举类要用关键字 enum;
2)所有枚举类都是Enum类的子类;
3)枚举项必须在第一行,以逗号分隔,最后一个枚举项后的分号可以省略。若枚举项后有其他的东西,这个分号就不能省略;
4)枚举类可以有构造器,但必须是private的,它默认的也是private的。
5)枚举类也可以有抽象方法,但是枚举项必须重写该方法。
6)枚举可以在switch语句中使用。(1.5版本可以接收枚举,1.7版本可以接收字符串)
5、应用场景
1)自定义枚举类
public class Number {
private String name;
private Number(String name) {
this.name = name;
}
public static final Number ONE = new Number("一");
public static final Number TWO = new Number("二");
public static final Number THREE = new Number("三");
}
2)使用enum来创建枚举类
public enum Number {
ONE("一"), TWO("二"), THREE("三");
private String name;
private Number(String name) {
this.name = name;
}
}
3)实现接口的枚举类(相当于让每个枚举项重写抽象方法)
public enum Number implements AutoCloseable {
ONE("一") {
public void close() {
System.out.println("one关闭");
}
}, TWO("二") {
public void close() {
System.out.println("two关闭");
}
}, THREE("三") {
public void close() {
System.out.println("three关闭");
}
}
}
六、泛型
1、泛型概述
泛型是一种广泛的类型,把明确数据类型的工作提前到了编译时期。
分类: 泛型类、泛型方法、泛型接口。
2、泛型好处
1)保证数据类型的安全性,避免强制类型转换的问题,简化代码的书写。 String str = list.get(i);
2)将运行时的问题提前到了编译期间。
3、使用方式
1)泛型类
格式: [修饰符] class 类名<泛型类型1,...> ==> public class Student<T> { }
2)泛型方法
格式: [修饰符] <泛型类型> 返回类型 方法名(泛型类型 变量名) ==> public <E> void eat(E e) { }
3)泛型接口
格式: public interface 接口名<泛型类型1,...> ==> public interface Inter<T> { }
4)泛型通配符 <?>,任意的Java类。
格式1(上限通配符): <? extends E>
。
只能是E及其子类。【?~E】
List<? extends Man> list = new ArrayList<Man>();
List<? extends Man> list = new ArrayList<Boy>();
读数据: 【看上限】上限类型为Man类型(不管该list如何赋值,里面存放的元素一定是Man类型) Man m = list.get(0);
写数据: 【看下限】没有明确下限类型(编译器并不能准确的给出能接收的类型)
只能接收null值,因为null值可以是任意类型。 list.add(null);
格式2(下限通配符): <? super E>
。
只能是E及其父类。【E~?】
List<? super Man> list = new ArrayList<Man>();
List<? super Man> list = new ArrayList<People>();
读数据: 【看上限】没有明确上限类型(编译器并不能准确给出能接收的具体类型),
但能确定存放的是Object类型,所以 上限默认为Object类型。 Object obj = list.get(0);
写数据: 【看下限】下限为Man类型(可以保证集合中的元素一定是Man类型,所以Man的子类元素也可以存放)。
4、注意事项
1)如果不使用泛型通配符,那么前后的泛型必须一致,或者后面的泛型可以不写(Java7新特性之菱形泛型)
List<String> list = new ArrayList<>();
2)泛型类必须是引用数据类型(类、接口、数组)。
5、应用场景
1)普通用法
List<String> list = new ArrayList<>;
2)泛型类
public class Tool<T> {
private T name;
public void setName(T name) {
this.name = name;
}
public T getName() {
return name;
}
}
3)泛型方法
public clas Tool<T> {
private T name;
public void setName(T name) {
this.name = name;
}
public T getName() {
return name;
}
// 方法泛型最好与类的泛型一致,如果不一致,需要在方法上声明该类型
public <E> void show(E e) {
System.out.println(e);
}
// 静态方法必须声明自己的泛型,注:此时的T和类上的T不是同一个类型
public static <T> void print(T t) {
System.out.println(t);
}
}
4)泛型接口
interface Inter<T> {
public void show(T t);
}
// 第一种方式:推荐使用这种
class Demo implements Inter<String> {
@Override
public void show(String t) {
System.out.println(t);
}
}
// 第二种方式:没有必要在实现接口的时候给自己类加泛型
class Demo<T> implements Inter<T> {
@Override
public void show(T t) {
System.out.println(t);
}
}
5)泛型通配符:
很多时候都是用它来当作方法中的形参。开发时我们都需要遵循PECS法则(“Producer Extends, Consumer Super”),也就是:
如果参数化类型表示一个生产者,就使用 <? extends T>
;
如果参数化类型表示一个消费者,就使用 <? super T>
。
A. 基本用法:
class People {
// 人
}
class Man extends People {
// 男人
}
class Woman extends People {
// 女人
}
class Boy extends Man {
// 男孩
}
main {
List<? extends Man> list = null;
list = new ArrayList<Man>();
list = new ArrayList<Boy>();
list = new ArrayList<People>(); // 编译错误
Man m = list.get(0);
list.add(null);
list.add(new Man()); // 编译错误
///
List<? super Man> list = null;
list = new ArrayList<Man>();
list = new ArrayList<People>();
list = new ArrayList<Boy>(); // 编译错误
Object obj = list.get(0);
list.add(new Man());
list.add(new Boy());
list.add(new People()); // 编译错误
}
B. 应用场景:
class Fruit {
// 水果
}
class Apple extends Fruit {
// 苹果
}
class RedApple extends Apple {
// 红苹果
}
class Pear extends Fruit {
// 梨
}
// 生产者
class Producer<E> {
public void produce(List<? extends E> list) {
// ...生产(写),看下限add,所以用extends来接收一个下限类型
}
}
main {
Producer<Fruit> p = new Producer<>();
List<Apple> apples = new ArrayList<>();
p.produce(apples);
// ==> List<? extends Fruit> list = new ArrayList<Apple>();
}
// 消费者
class Consumer<E> {
public E consume(List<? super E> list) {
// ...消费(读),看上限get,所以用super来接收一个上限类型
E e = (E) list.get(0);
return e;
}
}
main {
Consumer<RedApple> c = new Consumer<>();
List<RedApple> redApples = new ArrayList<>();
c.consume(redApples);
// ==> List<? super RedApple> list = new ArrayList<RedApple>();
List<Apple> apples = new ArrayList<>();
c.consume(apples);
// ==> List<? super RedApple> list = new ArrayList<Apple>();
}