期末复习 自留 重点只抓考点
目录
基本技术
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() {
@Override
public 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 {
@Override
public 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";
}
@Override
public 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
notifyAll
Declared methods:
getName
setName
privateMethod
getName 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() {
}
@Override
public String toString() {
return "Person{publicField='" + publicField + "', privateField='" + privateField + "'}";
}
}
运行结果
Public fields:
publicField
Declared fields:
publicField
privateField
publicField: public java.lang.String com.example.Person.publicField
privateField: private java.lang.String com.example.Person.privateField
Public 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基本概念
-
控制反转与依赖注入(代码)
考点:了解控制反转的基本模式,用依赖注入编写程序
见主页