期末复习 自留 重点只抓考点
目录
基本技术
SOCKETS网络套接字
多线程
数据序列化
Java I/O流
集合容器
范型
内部类、匿名类、Lambda(代码)
项目构建管理工具
高级技术
注解(代码)
反射(代码)
Stream api
动态代理设计模式
控制反转与依赖注入(代码)
应用案例
基本技术
-
SOCKETS网络套接字
-
多线程
-
数据序列化
-
Java I/O流
-
集合容器
Set 、List 、Map 、Iterator & Enumeration
-
范型
范型通配符?
<? super E >固定下界限定
<? extends E>固定上界限定
<?> 无限定
-
内部类、匿名类、Lambda(代码)
- 内部类
- 匿名类(内部类的简化)
- Lambda表达式(匿名类的简化):
- 一种函数式接口的实现对象 函数式接口-仅含一个方法 |
- 本质上是一个接口的匿名实现类的方法函数 |
- ::方法引用 |
内部类、匿名类和Lambda表达式都是Java中用于定义行为的方式。它们各有特点,并且可以相互转换。下面将通过具体例子说明这些概念及其关系。
内部类
内部类是定义在另一个类内部的类。它可以访问外部类的成员,包括私有成员。
public class OuterClass {private String outerField = "Outer field"; // 外部类的私有字段// 定义一个内部类public class InnerClass {public void display() {// 内部类可以访问外部类的私有字段System.out.println(outerField);}}// 创建内部类实例并调用其方法public void createInner() {InnerClass inner = new InnerClass(); // 创建内部类实例inner.display(); // 调用内部类的方法}public static void main(String[] args) {OuterClass outer = new OuterClass(); // 创建外部类实例outer.createInner(); // 调用方法创建并使用内部类}
}
匿名类
public class AnonymousClassExample {interface MyInterface {void display(); // 定义一个接口方法}// 使用匿名类实现接口public void createAnonymousClass() {MyInterface myInterface = new MyInterface() {@Overridepublic void display() {// 实现接口方法System.out.println("Anonymous class implementation");}};myInterface.display(); // 调用匿名类实现的方法}public static void main(String[] args) {AnonymousClassExample example = new AnonymousClassExample(); // 创建外部类实例example.createAnonymousClass(); // 调用方法使用匿名类}
}
Lambda表达式
对于lambda表达式来说,我们只需要入参和相关的执行逻辑即可
加上箭头,就成为了lambda表达式
public class LambdaExpressionExample {interface MyFunctionalInterface {void display(); // 定义一个函数式接口方法}// 使用Lambda表达式实现函数式接口public void createLambda() {MyFunctionalInterface myInterface = () -> {// Lambda表达式实现接口方法System.out.println("Lambda expression implementation");};myInterface.display(); // 调用Lambda表达式实现的方法}public static void main(String[] args) {LambdaExpressionExample example = new LambdaExpressionExample(); // 创建外部类实例example.createLambda(); // 调用方法使用Lambda表达式}
}
函数式接口
@FunctionalInterface
interface MyFunctionalInterface {void display(); // 仅含一个抽象方法的接口
}
方法引用
方法引用的语法是:类名::方法名,其中 类名 是包含方法的类的名称,方法名 是要引用的方法的名称。方法引用可以替换 Lambda 表达式,并在更简洁的形式下提供相同的功能。
方法引用的类型有四种:
静态方法引用 | ClassName::staticMethodName |
实例方法引用 | instance::methodName |
构造方法引用 | ClassName::new |
数组构造方法引用 | TypeName[]::new |
静态方法引用:
静态方法引用用于引用类的静态方法。
import java.util.Arrays;
import java.util.List;public class StaticMethodReferenceExample {public static void main(String[] args) {List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 使用 Lambda 表达式和静态方法引用打印集合中的元素names.forEach(name -> System.out.println(name));names.forEach(System.out::println);}
}
实例方法引用:
实例方法引用用于引用某个对象的实例方法。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class ConstructorReferenceExample {public static void main(String[] args) {List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 使用 Lambda 表达式和构造方法引用创建新集合List<String> upperCaseNames1 = names.stream().map(name -> new String(name.toUpperCase())).collect(Collectors.toList());List<String> upperCaseNames2 = names.stream().map(String::toUpperCase).collect(Collectors.toList());System.out.println(upperCaseNames1); // 输出: [ALICE, BOB, CHARLIE]System.out.println(upperCaseNames2); // 输出: [ALICE, BOB, CHARLIE]}
}
构造方法引用:
构造方法引用用于引用类的构造方法。
import java.util.function.Supplier;public class ConstructorReferenceExample {private String message;// 构造方法public ConstructorReferenceExample() {this.message = "Default Message";}public String getMessage() {return message;}public static void main(String[] args) {// 使用构造方法引用Supplier<ConstructorReferenceExample> supplier = ConstructorReferenceExample::new;// 创建新对象ConstructorReferenceExample example = supplier.get();System.out.println(example.getMessage()); // 输出: Default Message}
}
数组构造方法引用
数组构造方法引用用于引用数组的构造方法。
import java.util.function.Function;public class ArrayConstructorReferenceExample {public static void main(String[] args) {// 使用数组构造方法引用创建新数组Function<Integer, int[]> createIntArray = int[]::new;// 创建一个长度为5的整数数组int[] intArray = createIntArray.apply(5);// 输出数组长度以验证System.out.println("Array length: " + intArray.length);}
}
转换示例
内部类
public class ConversionExample {interface MyInterface {void display(); // 定义一个接口方法}// 定义一个内部类实现接口public class InnerClass implements MyInterface {@Overridepublic void display() {System.out.println("Inner class implementation");}}// 使用内部类public void useInnerClass() {MyInterface myInterface = new InnerClass(); // 创建内部类实例myInterface.display(); // 调用内部类实现的方法}public static void main(String[] args) {ConversionExample example = new ConversionExample(); // 创建外部类实例example.useInnerClass(); // 调用方法使用内部类}
}
1. 内部类:可以访问外部类的成员,包括私有成员。适合需要访问外部类成员的场景。
2. 匿名类:没有名称,适合快速定义接口或类的实现,通常用于一次性使用的场景。
3. Lambda表达式:简化了匿名类的使用,主要用于实现仅含一个抽象方法的函数式接口,更加简洁和易读。
4. 方法引用:Lambda表达式的更简洁形式,用于引用现有的方法,进一步简化代码。
通过这些示例和解释,可以清楚地理解内部类、匿名类和Lambda表达式的关系,并且可以在不同场景下相互转换。
-
项目构建管理工具
高级技术
-
注解(代码)
自定义一段代码
package com.kuang.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 自定义注解
public class Test03 {// 注解可以显示属性,如果没有默认值,我们就必须给注解赋值@MyAnnotation2()public void test() {}
}@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2 {// 注解的参数:参数类型 + 参数名 ()String name() default "";int age() default 0;int id() default -1; // 如果默认值为-1,代表不存在String[] schools() default {"上海大学", "下海大学"};
}
没有默认值的情况:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 自定义注解
public class Test03 {// 注解可以显示属性,如果没有默认值,我们就必须给注解赋值@MyAnnotation2(age = 18)public void test() {}
}@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2 {// 注解的参数:参数类型 + 参数名 ()String name() default "";int age();int id() default -1; // 如果默认值为-1,代表不存在String[] schools() default {"上海大学", "下海大学"};
}
-
反射(代码)
参考视频
考点:具体构建对象,执行方法,调用属性
构造一个简单的反射
// 什么是反射
public class Test02 {public static void main(String[] args) throws ClassNotFoundException {// 通过反射获取类的 Class 对象// Class.forName 方法会加载指定的类,并返回该类的 Class 对象Class<?> c1 = Class.forName("com.kuang.reflection.User");// 打印 Class 对象的信息System.out.println(c1);// 多次获取相同类的 Class 对象Class<?> c2 = Class.forName("com.kuang.reflection.User");Class<?> c3 = Class.forName("com.kuang.reflection.User");Class<?> c4 = Class.forName("com.kuang.reflection.User");// 验证一个类在内存中只有一个 Class 对象// 通过比较 Class 对象的 hashCode 来确认它们是同一个对象// hashCode 相同表示这些 Class 对象是同一个实例System.out.println(c2.hashCode());System.out.println(c3.hashCode());System.out.println(c4.hashCode());}
}// 实体类:pojo,entity
// 定义一个简单的 User 类,用于反射操作示例
class User {// 示例中的实体类 User 的定义// 这里可以包含一些属性和方法private String name;private int age;// 构造方法public User() {}public User(String name, int age) {this.name = name;this.age = age;}// Getter 和 Setter 方法public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}// 一个简单的方法public void printInfo() {System.out.println("Name: " + name + ", Age: " + age);}
}
获得Class的方法
1. `object.getClass()`:获取指定实例对象的 `Class`。
import java.util.ArrayList;
import java.util.List;public class Example1 {public static void main(String[] args) {List<String> list = new ArrayList<>();Class<?> listClass = list.getClass();System.out.println("Class name: " + listClass.getName());}
}
输出:
Class name: java.util.ArrayList
2. `Class.getSuperclass()`:获取当前 `Class` 对象的继承类 `Class`。
import java.util.ArrayList;public class Example2 {public static void main(String[] args) {Class<?> listClass = ArrayList.class;Class<?> superClass = listClass.getSuperclass();System.out.println("Superclass name: " + superClass.getName());}
}
输出:
Superclass name: java.util.AbstractList
3. `Object.class`:`.class` 直接获取 `Class`。
public class Example3 {public static void main(String[] args) {Class<?> listClass = ArrayList.class;System.out.println("Class name: " + listClass.getName());}
}
输出:
Class name: java.util.ArrayList
4. `Class.forName(类名)` :用 `Class` 的静态方法传入类的全名来获取 `Class` 对象。
public class Example4 {public static void main(String[] args) {try {Class<?> c = Class.forName("java.util.ArrayList");System.out.println("Class name: " + c.getName());} catch (ClassNotFoundException e) {e.printStackTrace();}}
}
输出:
Class name: java.util.ArrayList
5. `Primitive.TYPE`:基本数据类型的封装类获取 `Class` 的方式。
public class Example5 {public static void main(String[] args) {Class<?> longClass = Long.TYPE;Class<?> integerClass = Integer.TYPE;Class<?> voidClass = Void.TYPE;System.out.println("Long class: " + longClass.getName());System.out.println("Integer class: " + integerClass.getName());System.out.println("Void class: " + voidClass.getName());}
}
输出:
Long class: long
Integer class: int
Void class: void
通过反射实例化对象
平常情况我们通过new Object来生成一个类的实例,但有时候我们没法直接new,只能通过反射动态生成。
实例化无参构造函数的对象,两种方式:
①Class. newInstance();
②Class. getConstructor (new Class[]{}).newInstance(new Object[]{})
实例化带参构造函数的对象:
Class. getConstructor(Class<?>... parameterTypes) . newInstance(Object... initargs)
// 定义Person类
package com.example;public class Person {private String name;public Person() {this.name = "Default Name";}@Overridepublic String toString() {return "Person{name='" + name + "'}";}
}
示例 1:使用 `Class.newInstance()` 实例化无参构造函数对象
public class Example1 {public static void main(String[] args) {try {// 获取Class对象Class<?> clazz = Class.forName("com.example.Person");// 通过Class.newInstance()实例化对象Object instance = clazz.newInstance();// 打印实例对象信息System.out.println(instance);} catch (Exception e) {e.printStackTrace();}}
}
输出:
Person{name='Default Name'}
示例 2:使用 `Class.getConstructor().newInstance()` 实例化无参构造函数对象
public class Example2 {public static void main(String[] args) {try {// 获取Class对象Class<?> clazz = Class.forName("com.example.Person");// 通过getConstructor().newInstance()实例化对象Object instance = clazz.getConstructor().newInstance();// 打印实例对象信息System.out.println(instance);} catch (Exception e) {e.printStackTrace();}}
}
输出:
Person{name='Default Name'}
示例 3:实例化带参构造函数的对象
public class Example3 {public static void main(String[] args) {try {// 获取Class对象Class<?> clazz = Class.forName("com.example.Person");// 获取带有String参数的构造函数java.lang.reflect.Constructor<?> constructor = clazz.getConstructor(String.class);// 通过构造函数实例化对象,并传递参数Object instance = constructor.newInstance("John Doe");// 打印实例对象信息System.out.println(instance);} catch (Exception e) {e.printStackTrace();}}
}
输出:
Person{name='John Doe'}
通过反射调用Method(方法)
获得当前类以及超类的public Method: Method[] arrMethods = classType. getMethods();
获得当前类申明的所有Method: Method[] arrMethods = classType. getDeclaredMethods();
获得当前类以及超类指定的public Method: Method method = classType. getMethod(String name, Class<?>... parameterTypes);
获得当前类申明的指定的Method: Method method = classType. getDeclaredMethod(String name, Class<?>... parameterTypes)
通过反射动态运行指定Method: Object obj = method. invoke(Object obj, Object... args)
import java.lang.reflect.Method;public class ReflectionExample {public static void main(String[] args) {try {// 获取Class对象Class<?> clazz = Class.forName("com.example.Person");// 获取当前类及其超类的public方法Method[] publicMethods = clazz.getMethods();System.out.println("Public methods:");for (Method method : publicMethods) {System.out.println(method.getName());}// 获取当前类声明的所有方法Method[] declaredMethods = clazz.getDeclaredMethods();System.out.println("\nDeclared methods:");for (Method method : declaredMethods) {System.out.println(method.getName());}// 获取当前类及其超类指定的public方法Method getNameMethod = clazz.getMethod("getName");System.out.println("\ngetName method: " + getNameMethod);// 获取当前类声明的指定方法Method setNameMethod = clazz.getDeclaredMethod("setName", String.class);System.out.println("\nsetName method: " + setNameMethod);// 通过反射动态运行指定方法Object personInstance = clazz.getConstructor().newInstance();// 运行setName方法setNameMethod.invoke(personInstance, "John Doe");// 运行getName方法Object name = getNameMethod.invoke(personInstance);System.out.println("\nName: " + name);} catch (Exception e) {e.printStackTrace();}}
}// 定义Person类
package com.example;public class Person {private String name;public Person() {this.name = "Default Name";}public String getName() {return name;}public void setName(String name) {this.name = name;}private void privateMethod() {System.out.println("This is a private method.");}
}
运行结果
Public methods:
getName
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAllDeclared methods:
getName
setName
privateMethodgetName method: public java.lang.String com.example.Person.getName()setName method: public void com.example.Person.setName(java.lang.String)Name: John Doe
1. 获取 `Class` 对象:
Class<?> clazz = Class.forName("com.example.Person");
- 通过类的全限定名获取 `Class` 对象。
2. 获取当前类及其超类的 `public` 方法:
Method[] publicMethods = clazz.getMethods();
- 使用 `getMethods` 方法获取当前类及其超类的所有 `public` 方法。
3. 获取当前类声明的所有方法:
Method[] declaredMethods = clazz.getDeclaredMethods();
- 使用 `getDeclaredMethods` 方法获取当前类声明的所有方法(包括 `public`、`protected`、`default` 和 `private` 方法)。
4. 获取当前类及其超类指定的 `public` 方法:
Method getNameMethod = clazz.getMethod("getName");
- 使用 `getMethod` 方法获取当前类及其超类中指定的 `public` 方法。
5. 获取当前类声明的指定方法:
Method setNameMethod = clazz.getDeclaredMethod("setName", String.class);
- 使用 `getDeclaredMethod` 方法获取当前类声明的指定方法。
6.通过反射动态运行指定方法:
Object personInstance = clazz.getConstructor().newInstance();
setNameMethod.invoke(personInstance, "John Doe");
Object name = getNameMethod.invoke(personInstance);
- 通过 `clazz.getConstructor().newInstance()` 创建类的实例。
- 使用 `invoke` 方法调用 `setName` 和 `getName` 方法。
通过反射调用Field(变量)
获得当前类以及超类的public Field: Field[] arrFields = classType. getFields();
获得当前类申明的所有Field: Field[] arrFields = classType. getDeclaredFields();
获得当前类以及超类指定的public Field: Field field = classType. getField(String name);
获得当前类申明的指定的Field: Field field = classType. getDeclaredField(String name);
通过反射动态设定Field的值: fieldType.set(Object obj, Object value);
通过反射动态获取Field的值: Object obj = fieldType. get(Object obj) ;
import java.lang.reflect.Field;public class ReflectionFieldExample {public static void main(String[] args) {try {// 获取Class对象Class<?> clazz = Class.forName("com.example.Person");// 获取当前类及其超类的public字段Field[] publicFields = clazz.getFields();System.out.println("Public fields:");for (Field field : publicFields) {System.out.println(field.getName());}// 获取当前类声明的所有字段Field[] declaredFields = clazz.getDeclaredFields();System.out.println("\nDeclared fields:");for (Field field : declaredFields) {System.out.println(field.getName());}// 获取当前类及其超类指定的public字段Field publicField = clazz.getField("publicField");System.out.println("\npublicField: " + publicField);// 获取当前类声明的指定字段Field privateField = clazz.getDeclaredField("privateField");System.out.println("\nprivateField: " + privateField);// 创建Person类的实例Object personInstance = clazz.getConstructor().newInstance();// 通过反射动态设定字段的值publicField.set(personInstance, "Public Field Value");privateField.setAccessible(true); // 设置私有字段可访问privateField.set(personInstance, "Private Field Value");// 通过反射动态获取字段的值Object publicFieldValue = publicField.get(personInstance);Object privateFieldValue = privateField.get(personInstance);System.out.println("\nPublic Field Value: " + publicFieldValue);System.out.println("Private Field Value: " + privateFieldValue);} catch (Exception e) {e.printStackTrace();}}
}// 定义Person类
package com.example;public class Person {public String publicField = "Initial Public Field Value";private String privateField = "Initial Private Field Value";public Person() {}@Overridepublic String toString() {return "Person{publicField='" + publicField + "', privateField='" + privateField + "'}";}
}
运行结果
Public fields:
publicFieldDeclared fields:
publicField
privateFieldpublicField: public java.lang.String com.example.Person.publicFieldprivateField: private java.lang.String com.example.Person.privateFieldPublic Field Value: Public Field Value
Private Field Value: Private Field Value
1. 获取 `Class` 对象:
Class<?> clazz = Class.forName("com.example.Person");
- 通过类的全限定名获取 `Class` 对象。
2. 获取当前类及其超类的 `public` 字段:
Field[] publicFields = clazz.getFields();
- 使用 `getFields` 方法获取当前类及其超类的所有 `public` 字段。
3. 获取当前类声明的所有字段:
Field[] declaredFields = clazz.getDeclaredFields();
- 使用 `getDeclaredFields` 方法获取当前类声明的所有字段(包括 `public`、`protected`、`default` 和 `private` 字段)。
4. 获取当前类及其超类指定的 `public` 字段:
Field publicField = clazz.getField("publicField");
- 使用 `getField` 方法获取当前类及其超类中指定的 `public` 字段。
5. 获取当前类声明的指定字段:
Field privateField = clazz.getDeclaredField("privateField");
- 使用 `getDeclaredField` 方法获取当前类声明的指定字段。
6. 通过反射动态设定字段的值:
publicField.set(personInstance, "Public Field Value");
privateField.setAccessible(true); // 设置私有字段可访问
privateField.set(personInstance, "Private Field Value");
- 使用 `set` 方法设置字段的值。
- 使用 `setAccessible(true)` 方法使私有字段可访问。
7. 通过反射动态获取字段的值:
Object publicFieldValue = publicField.get(personInstance);
Object privateFieldValue = privateField.get(personInstance);
- 使用 `get` 方法获取字段的值。
-
Stream api
-
动态代理设计模式
考点:不使用框架,掌握AOP基本概念
-
控制反转与依赖注入(代码)
考点:了解控制反转的基本模式,用依赖注入编写程序
见主页