一、泛型
import java.util.Comparator;
class MyArray<T> { // 泛型类语法
Object[] arr = new Object[5];
public void setArr(int pos, T val) {
this.arr[pos] = val;
}
public T getArr(int pos) {
return (T) arr[pos];
}
}
class StringMyArray extends MyArray<String>{ // 继承时尖括号内需要填写
@Override // 由于参数列表不相同,此类中 setArr 方法未覆盖父类,因此编译器会在 StringMyArray 类中生成桥接方法
public void setArr(int pos, String val) {
super.setArr(pos, val);
}
}
class MyArray2<E extends Comparator<E>> {
// 使用 extends 规定泛型的上届,即传入类型的边界
// 例如,E必须实现的了 Comparator 接口
}
class util { // 泛型方法语法
public static <T> void swap(T[] arr, int i, int j) { // 在返回类型前加上 <T>
T tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
public class GenericClass {
public static void main(String[] args) {
MyArray<Integer> myArray = new MyArray<>(); // 泛型类的实例化
myArray.setArr(1, 2);
int ret = myArray.getArr(5);
System.out.println(ret);
util.swap(new Integer[]{1, 2, 3}, 1, 2); // 传入的必须为包装类型
}
}
class Food {}
class Fruit extends Food{}
class Apple extends Fruit {}
class Banana extends Fruit {}
class Plate<T> { // 设置泛型
private T data ;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
class TestDemo { // 通配符上届,下届同理
public static void main(String[] args) {
Plate<Apple> plate = new Plate<>();
plate.setData(new Apple());
fun(plate); // 只能传入 Fruit 及其子类
Plate<Banana> plate2 = new Plate<>();
plate2.setData(new Banana());
fun(plate2);
}
public static void fun(Plate<? extends Fruit> temp){
// 此时⽆法在fun函数中对temp进⾏添加元素,因为temp接收的是Fruit和他的⼦类,此时存储的元素应该是哪个⼦类⽆法确定。所以添加会报错!
// temp.setData(new Banana()); error
// temp.setData(new Apple()); error
System.out.println(temp.getData());
}
}
二、反射
这里有一个学生类。通过反射可以在运行时检查,访问和修改类,接口,字段和方法的机制。
public class Student {
private String name = "meat";
private int age = 18;
public Student() {
System.out.println("Student()");
}
private Student(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println("meat eat");
}
public void sleep() {
System.out.println("meat sleep");
}
public void func(String str) {
System.out.println(str);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
获取Class对象
通过Class.forName()
class Test {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> stu1 = Class.forName("Student");
}
}
- 使用"包名.类名"获取
- 返回值是
Class<?> - 需要抛出异常。
- 使用频率最多
通过类名.class
class Test {
public static void main(String[] args) {
Class<?> stu2 = Student.class;
}
}
使用类对象的getClass方法
class Test {
public static void main(String[] args) {
Student student = new Student();
Class<?> stu3 = student.getClass();
}
}
注意:需要先实例化对象,且无论获取了几次,这个Class对象只有一个。
通过Class对象实例化类
class Test {
public static void main(String[] args) {
Class<?> stu;
try {
stu = Class.forName("Student");
Student student = (Student) stu.newInstance();
System.out.println(student);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
- 使用stu.newInstance()方法获取Student对象。
- 返回值是泛型,因此需要强制转换。
- 此时调用的是Student类不带参数的构造方法。
- 缺点:代码量大,效率不高。
获取对象的构造方法
class Test {
public static void main(String[] args) {
Class<?> stu;
try {
stu = Class.forName("Student");
Constructor<?> constructor = stu.getDeclaredConstructor(String.class, int.class);
constructor.setAccessible(true);
Student student = (Student) constructor.newInstance("肉肉", 1);
System.out.println(student);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
1.通过类名.getDeclaredConstructor(可变参数)方法获取类的构造方法
2.在通过constructor实例化对象前,需要setAccessible()为true
修改对象的字段
class Test {
public static void main(String[] args) {
Class<?> stu;
try {
stu = Class.forName("Student");
Field field = stu.getDeclaredField("name");
field.setAccessible(true);
Student student = (Student) stu.newInstance();
field.set(student, "肥肉肉"); // 1. 修改哪个对象 2. 修改成什么
System.out.println(student);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
}
调用对象的方法
class Test {
public static void main(String[] args) {
Class<?> stu;
try {
stu = Class.forName("Student");
Method method = stu.getDeclaredMethod("func", String.class);
Student student = (Student) stu.newInstance();
method.setAccessible(true);
method.invoke(student, "吃肉肉");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
三、枚举
所有的Enum都默认继承于Enum类。
public enum Color {
RED, YELLOW, BLUE;
}
使用
public enum Color {
RED, YELLOW, BLUE;
public static void main(String[] args) {
Color color = RED;
switch (color) {
case RED:
System.out.println(RED);
break;
case BLUE:
System.out.println(BLUE);
break;
case YELLOW:
System.out.println(YELLOW);
break;
default:
System.out.println("null");
break;
}
}
}
常用方法
public enum Color {
RED, YELLOW, BLUE;
public static void main(String[] args) {
Color[] colors = Color.values();
for (int i = 0; i < colors.length; i++) {
System.out.println(colors[i] + "-->" + colors[i].ordinal());
}
Color tmp = Color.valueOf("RED");
System.out.println(tmp);
System.out.println(RED.compareTo(YELLOW));
}
}
.values()以数组形式返回枚举所有成员.ordinal()获取枚举成员的索引位置.valueOf()将字符串转换为枚举实例compareTo()比较两个枚举成员下标
枚举
Enum的构造方法默认是私有的,但反射不能创造枚举实例。
下面代码运行会报错。
public enum Color{
RED("红色", 1), YELLOW("黄色", 2), BLUE("蓝色", 3);
private String name;
private int key;
Color(String name, int key) {
this.name = name;
this.key = key;
}
}
class main {
public static void main(String[] args) {
Class<?> col;
try {
col = Class.forName("Color");
Constructor<?> constructor = col.getDeclaredConstructor(String.class, int.class, String.class, int.class);
constructor.setAccessible(true);
Color color = (Color) constructor.newInstance("棕色", 4, "黑色", 4);
System.out.println(color);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
四、lambda表达式
函数式接口
只有一个方法的接口叫做函数式接口,可以用@FunctionalInterface声明。
@FunctionalInterface
public interface Test {
void test();
}
lambda表达式是匿名内部类的简化。实际上lambda表达式创建了一个类,实现接口,重写方法。
lambda表达式语法
lambda表达式基本语法:()-> {}
其中:
()内填写参数->可以理解为被用于{}填写表达式或代码块
lambda表达式简写
- 传入的参数类型可以省略
- 如果需传入一个参数,则
()可以省略 - 如果方法体只有一句代码,则
{}可以省略 - 如果方法体只有一条
return语句,那么{}和return都可以省略
注意!lambda表达式简化的是重写方法的过程!
变量捕获
@FunctionalInterface
public interface lambda {
void test();
}
public class Test {
public static void main(String[] args) {
int a = 100;
lambda lambda = new lambda() {
@Override
public void test() {
a = 10; // 报错
System.out.println(a);
}
};
lambda.test();
}
}
打印元素
import java.util.ArrayList;
import java.util.function.Consumer;
public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("Hello");
list.add("meat");
list.add("OK!");
/*list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
list.forEach(s -> System.out.println(s));
}
}
排序元素
import java.util.ArrayList;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("Hello");
list.add("meat");
list.add("OK!");
/*list.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});*/
list.sort(((o1, o2) -> o1.compareTo(o2)));
}
}

参与讨论
(Participate in the discussion)
参与讨论