1.JavaWebJava基础加强[万字长文]-Junit、反射、注解核心知识点梳理

导语:

一、Junit单元测试

1.Junit测试概述

2.Junit使用步骤

3.Junit_@Before&@After

二、反射

1.反射概述

2.反射获取字节码Class对象的三种方式

3.Class对象功能概述

4.Class对象功能_获取Field

5.Class对象功能_获取Constructor

6.Class对象功能_获取Method

7.反射案例

三、注解

1.注解概念

2.JDK内置注解

3.自定义注解_格式&本质

4.自定义注解_属性定义

5.自定义注解_元注解

6.解析注解

7.注解案例_简单的测试框架

结语:


导语:

    这篇文档详细介绍了Java编程中Junit测试、反射原理和注解应用的核心知识点,旨在帮助初学者掌握Java基础,也可作为进阶学习的参考资料。

一、Junit单元测试

1.Junit测试概述

  • 黑盒测试:无需编写代码,只需给输入值,检查输出是否符合预期。

  • 白盒测试:需要编写代码,关注程序的具体执行流程。

案例代码:
    展示了如何使用JUnit进行黑盒测试和白盒测试:


public class Calculator {public int add(int a, int b) {return a + b;}public int subtract(int a, int b) {return a - b;}
}

import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;public class CalculatorTest {private Calculator calculator;@Beforepublic void setUp() {calculator = new Calculator();}// 黑盒测试@Testpublic void testAdd() {int result = calculator.add(1, 2);assertEquals(3, result);}// 白盒测试@Testpublic void testSubtract() {int result = calculator.subtract(5, 3);assertEquals(2, result);}
}

2.Junit使用步骤

  • 定义测试类(以Test结尾)

  • 定义测试方法(以test开头)

  • 给测试方法添加@Test注解

  • 导入Junit依赖

案例代码:


import org.junit.Assert;
import org.junit.Test;public class CalculatorTest {@Testpublic void testAdd() {Calculator c = new Calculator();int result = c.add(1, 2);Assert.assertEquals(3, result);}@Testpublic void testSubtract() {Calculator c = new Calculator();int result = c.subtract(5, 3);Assert.assertEquals(2, result);}
}

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope>
</dependency>

3.Junit_@Before&@After

  • @Before:初始化方法,在测试方法执行前自动执行

  • @After:释放资源方法,在测试方法执行后自动执行

代码案例:


import org.junit.After;
import org.junit.Before;
import org.junit.Test;public class CalculatorTest {private Calculator calculator;@Beforepublic void setUp() {// 初始化操作calculator = new Calculator();System.out.println("setUp...");}@Afterpublic void tearDown() {// 释放资源calculator = null;System.out.println("tearDown...");}@Testpublic void testAdd() {int result = calculator.add(1, 2);Assert.assertEquals(3, result);}@Testpublic void testSubtract() {int result = calculator.subtract(5, 3);Assert.assertEquals(2, result);}
}

二、反射

1.反射概述

  • 将类的各个组成部分封装为其他对象

  • 好处:在运行时操作对象,提高程序扩展性

代码案例:


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;public class ReflectionExample {public static void main(String[] args) {try {// 获取类的Class对象Class<?> personClass = Class.forName("Person");// 获取所有public字段Field[] fields = personClass.getFields();for (Field field : fields) {System.out.println("Public field: " + field);}// 获取所有public方法Method[] methods = personClass.getMethods();for (Method method : methods) {System.out.println("Public method: " + method);}// 获取所有public构造器Constructor<?>[] constructors = personClass.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println("Public constructor: " + constructor);}} catch (ClassNotFoundException e) {e.printStackTrace();}}
}

2.反射获取字节码Class对象的三种方式

  • Class.forName()

  • 类名.class

  • 对象.getClass()

代码案例:

public class ReflectionExample {public static void main(String[] args) {// 方式1:使用Class.forName()try {Class<?> personClass1 = Class.forName("Person");System.out.println(personClass1);} catch (ClassNotFoundException e) {e.printStackTrace();}// 方式2:使用类名.classClass<?> personClass2 = Person.class;System.out.println(personClass2);// 方式3:使用对象.getClass()Person person = new Person();Class<?> personClass3 = person.getClass();System.out.println(personClass3);}
}

3.Class对象功能概述

  • 获取成员变量

  • 获取构造方法

  • 获取成员方法

  • 获取全类名

案例代码:

public class ReflectionExample {public static void main(String[] args) {try {// 获取Person类的Class对象Class<?> personClass = Class.forName("Person");// 获取所有成员变量Field[] fields = personClass.getDeclaredFields();for (Field field : fields) {System.out.println("Field: " + field);}// 获取所有构造方法Constructor<?>[] constructors = personClass.getDeclaredConstructors();for (Constructor<?> constructor : constructors) {System.out.println("Constructor: " + constructor);}// 获取所有成员方法Method[] methods = personClass.getDeclaredMethods();for (Method method : methods) {System.out.println("Method: " + method);}// 获取全类名String className = personClass.getName();System.out.println("Full class name: " + className);} catch (ClassNotFoundException e) {e.printStackTrace();}}
}

4.Class对象功能_获取Field

  • Field[] getFields()

  • Field getField(String name)

  • Field[] getDeclaredFields()

  • Field getDeclaredField(String name)

案例代码:

public class ReflectionExample {public static void main(String[] args) {try {// 获取Person类的Class对象Class<?> personClass = Class.forName("Person");// 获取所有public字段Field[] publicFields = personClass.getFields();for (Field field : publicFields) {System.out.println("Public Field: " + field);}// 获取指定名称的public字段Field publicField = personClass.getField("name");System.out.println("Specific Public Field: " + publicField);// 获取所有字段(包括private)Field[] allFields = personClass.getDeclaredFields();for (Field field : allFields) {System.out.println("Field: " + field);}// 获取指定名称的字段(包括private)Field privateField = personClass.getDeclaredField("age");System.out.println("Specific Field: " + privateField);} catch (ClassNotFoundException | NoSuchFieldException e) {e.printStackTrace();}}
}

5.Class对象功能_获取Constructor

  • Constructor[] getConstructors()

  • Constructor getConstructor(参数类型…)

  • Constructor getDeclaredConstructor(参数类型…)

  • Constructor[] getDeclaredConstructors()

案例代码:

public class ReflectionExample {public static void main(String[] args) {try {// 获取Person类的Class对象Class<?> personClass = Class.forName("Person");// 获取所有public构造器Constructor<?>[] publicConstructors = personClass.getConstructors();for (Constructor<?> constructor : publicConstructors) {System.out.println("Public Constructor: " + constructor);}// 获取指定参数的public构造器Constructor<?> publicConstructor = personClass.getConstructor(String.class);System.out.println("Specific Public Constructor: " + publicConstructor);// 获取所有构造器(包括private)Constructor<?>[] allConstructors = personClass.getDeclaredConstructors();for (Constructor<?> constructor : allConstructors) {System.out.println("Constructor: " + constructor);}// 获取指定参数的构造器(包括private)Constructor<?> privateConstructor = personClass.getDeclaredConstructor(String.class, int.class);System.out.println("Specific Constructor: " + privateConstructor);} catch (ClassNotFoundException | NoSuchMethodException e) {e.printStackTrace();}}
}

6.Class对象功能_获取Method

  • Method[] getMethods()

  • Method getMethod(String name, 参数类型…)

  • Method[] getDeclaredMethods()

  • Method getDeclaredMethod(String name, 参数类型…)

案例代码:

public class ReflectionExample {public static void main(String[] args) {try {// 获取Person类的Class对象Class<?> personClass = Class.forName("Person");// 获取所有public方法Method[] publicMethods = personClass.getMethods();for (Method method : publicMethods) {System.out.println("Public Method: " + method);}// 获取指定名称和参数的public方法Method publicMethod = personClass.getMethod("setName", String.class);System.out.println("Specific Public Method: " + publicMethod);// 获取所有方法(包括private)Method[] allMethods = personClass.getDeclaredMethods();for (Method method : allMethods) {System.out.println("Method: " + method);}// 获取指定名称和参数的方法(包括private)Method privateMethod = personClass.getDeclaredMethod("showAge");System.out.println("Specific Method: " + privateMethod);} catch (ClassNotFoundException | NoSuchMethodException e) {e.printStackTrace();}}
}

7.反射案例

  • 从配置文件读取类名和方法名

  • 使用反射加载类、创建对象、执行方法

案例代码:

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;public class ReflectionExample {public static void main(String[] args) {try {// 加载配置文件Properties properties = new Properties();InputStream inputStream = ReflectionExample.class.getClassLoader().getResourceAsStream("config.properties");properties.load(inputStream);// 读取配置文件中的类名和方法名String className = properties.getProperty("class.name");String methodName = properties.getProperty("method.name");// 使用反射加载类Class<?> classObj = Class.forName(className);// 使用反射创建对象Object obj = classObj.newInstance();// 使用反射执行方法Method method = classObj.getMethod(methodName);method.invoke(obj);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}

三、注解

1.注解概念

  • 说明程序,给计算机看的

  • 分类:文档、代码分析、编译检查

案例代码

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 文档注解
@Deprecated
public class AnnotationExample {// 编译检查注解@Overridepublic String toString() {return "This is a overridden toString method";}// 代码分析注解@SuppressWarnings("unchecked")public void analyzeCode() {// 这里会有类型转换的警告Object obj = new Object();String str = (String) obj;}// 自定义注解@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation {String value() default "";}@MyAnnotation("Hello")public void annotatedMethod() {System.out.println("Annotated method");}
}

2.JDK内置注解

  • @Override

  • @Deprecated

  • @SuppressWarnings

案例代码:


public class AnnotationExample {// 使用@Override注解标记重写父类方法@Overridepublic String toString() {return "This is a overridden toString method";}// 使用@Deprecated注解标记已过时的方法@Deprecatedpublic void oldMethod() {System.out.println("This is an old method");}// 使用@SuppressWarnings注解压制编译器警告@SuppressWarnings("unchecked")public void analyzeCode() {// 这里会有类型转换的警告Object obj = new Object();String str = (String) obj;}
}

3.自定义注解_格式&本质

  • 本质是接口,默认继承Annotation接口

案例代码:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 定义一个自定义注解
@Target(ElementType.METHOD) // 注解的作用目标
@Retention(RetentionPolicy.RUNTIME) // 注解的保留策略
public @interface MyAnnotation {// 定义一个value属性String value();
}// 使用自定义注解
public class AnnotationExample {// 在方法上使用自定义注解,并指定value属性值@MyAnnotation(value = "Hello")public void annotatedMethod() {System.out.println("Annotated method");}
}

4.自定义注解_属性定义

  • 返回值类型:基本数据类型、String、枚举、注解、数组

  • 属性赋值

案例代码:


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 定义一个自定义注解
@Target(ElementType.METHOD) // 注解的作用目标
@Retention(RetentionPolicy.RUNTIME) // 注解的保留策略
public @interface MyAnnotation {// 定义一个String类型的value属性,并指定默认值为"Hello"String value() default "Hello";// 定义一个int类型的age属性int age();// 定义一个枚举类型的gender属性Gender gender();// 定义一个注解类型的anno属性MyAnnotation2 anno();// 定义一个String数组类型的tags属性String[] tags();
}// 定义一个枚举类型
enum Gender {MALE, FEMALE
}// 定义一个自定义注解
@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation2 {String value();
}// 使用自定义注解
public class AnnotationExample {// 在方法上使用自定义注解,并为所有属性赋值@MyAnnotation(value = "World", age = 30, gender = Gender.MALE, anno = @MyAnnotation2("anno2"), tags = {"tag1", "tag2"})public void annotatedMethod() {System.out.println("Annotated method");}
}

5.自定义注解_元注解

  • @Target

  • @Retention

  • @Documented

  • @Inherited

案例代码:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 定义一个自定义注解
@Target(ElementType.METHOD) // 指定该注解只能用于方法
@Retention(RetentionPolicy.RUNTIME) // 指定注解保留到运行时
@Documented // 指定该注解会被包含在javadoc中
@Inherited // 指定该注解可以被继承
public @interface MyAnnotation {// 定义一个String类型的value属性,并指定默认值为"Hello"String value() default "Hello";
}// 使用自定义注解
public class AnnotationExample {// 在方法上使用自定义注解@MyAnnotation("World")public void annotatedMethod() {System.out.println("Annotated method");}
}// 继承了父类的注解
public class ChildClass extends AnnotationExample {// 子类会继承父类的@MyAnnotation注解@Overridepublic void annotatedMethod() {System.out.println("Child class");}
}

6.解析注解

  • 获取注解定义位置的对象

  • 获取指定的注解

  • 调用注解方法获取属性值

案例代码:


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 定义一个自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {// 定义一个String类型的value属性String value();
}// 使用自定义注解
public class AnnotationExample {// 在方法上使用自定义注解,并指定value属性值@MyAnnotation(value = "Hello")public void annotatedMethod() {System.out.println("Annotated method");}
}// 解析注解
public class AnnotationParser {public static void main(String[] args) throws Exception {// 获取方法对象Method method = AnnotationExample.class.getMethod("annotatedMethod");// 获取方法上的MyAnnotation注解MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);// 调用注解方法获取value属性值String value = myAnnotation.value();// 输出value属性值System.out.println("Value: " + value);}
}

7.注解案例_简单的测试框架

  • 自定义注解

  • 定义测试类

  • 执行测试

案例代码:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;// 定义一个自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {// 定义一个String类型的value属性String value();
}// 定义一个测试类
public class TestClass {// 定义一个测试方法,并使用自定义的Test注解@Test(value = "测试 add 方法")public void testAdd() {int result = 1 + 2;assertEquals(3, result);}@Test(value = "测试 subtract 方法")public void testSubtract() {int result = 5 - 3;assertEquals(2, result);}// 定义一个断言方法public static void assertEquals(int expected, int actual) {if (expected != actual) {throw new RuntimeException("测试失败:期望值=" + expected + " 实际值=" + actual);}}
}// 执行测试
public class TestRunner {public static void main(String[] args) {Class<?> testClass = TestClass.class;try {// 获取测试类对象Object testInstance = testClass.newInstance();// 遍历测试类中的所有方法for (Method method : testClass.getMethods()) {// 检查方法是否使用了Test注解if (method.isAnnotationPresent(Test.class)) {try {// 执行测试方法method.invoke(testInstance);System.out.println("测试成功:" + method.getAnnotation(Test.class).value());} catch (Exception e) {System.out.println("测试失败:" + method.getAnnotation(Test.class).value());}}}} catch (Exception e) {e.printStackTrace();}}
}

结语:

    以上内容涵盖了JUnit单元测试、反射机制、注解的概念及自定义,以及如何解析注解并应用在简单的测试框架案例中。这些知识点对于Java后端开发中的框架设计、代码规范以及测试都非常重要。通过这些知识点的学习,可以加深对Java高级特性的理解,并为后续框架学习和项目开发打下基础。

#JavaWeb

欢迎大家交流,金三银四求职季期间关注公众号送面试宝典。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/726081.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20个实操保姆级副业项目

这边免费给到大家很多项目资料和工具&#xff0c;主要的就是为了消除信息壁垒&#xff0c;在互联网创业或兼职的路上不再被割&#xff0c;不再多花冤枉钱&#xff0c;相信人间有真爱&#xff0c;有不懂的问题可咨询博主&#xff01;为了帮助到更多的创业者&#xff0c;资料欢迎…

极狐GitLab 16.3 重磅发布,极致的 DevOps 体验等你来【一】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 极狐GitLab 在去年 8 月份发布了 16.3 版本。此次发布带来了合…

ElasticSearch为什么快?

ElasticSearch是一个高性能&#xff0c;分布式搜索引擎&#xff0c;它之所以快&#xff0c;主要有以下几个原因&#xff1a; 1.分布式存储&#xff1a;ElasticSearch使用分布式存储技术&#xff0c;将数据存储在多个节点上从而减少单个节点的压力&#xff0c;提高整体性能。 …

Kakarot:当今以太坊的未来

1. 引言 前序博客&#xff1a; Kakarot&#xff1a;部署在Starknet上的ZK-EVM type 3 随着 Kakarot zkEVM 即将发布测试网&#xff0c;想重申下 Kakarot zkEVM 的愿景为&#xff1a; 为什么在rollup空间中还需要另一个 zkEVM&#xff1f; 开源代码见&#xff1a; https:/…

Anaconda prompt运行打开jupyter notebook 指令出错

一、打不开jupyter notebook网页 报错如下&#xff1a; Traceback (most recent call last): File “D:\anaconda3\lib\site-packages\notebook\traittypes.py”, line 235, in _resolve_classes klass self._resolve_string(klass) File “C:\Users\DELL\AppData\Roaming\Py…

oracle数据库通过sql实现blob类型字段转字符串

最近遇到一个问题&#xff0c;数据表tabA中有一个字段content是blob类型。现在需要通过sql把这个字段的内容展示出来。一般情况我们都是通过后端实现blob转string。但是通过sql查询出blob类型的内容还没遇到过&#xff0c;今天把解决这个问题的心理路程记录下。 首先&#xff0…

软考 系统分析师系列知识点之系统性能评估(3)

接前一篇文章&#xff1a;软考 系统分析师系列知识点之系统性能评估&#xff08;2&#xff09; 所属章节&#xff1a; 第6章. 系统配置与性能评价 第8节. 系统性能评估 6.8.2 经典评估方法 在计算机技术的发展过程中&#xff0c;性能评估的常用方法有&#xff1a;时钟频率法、…

vue3项目绝对路径重命名后vscode无法提示路径,无法进行文件跳转

vue3项目绝对路径重命名后vscode无法提示路径 设置如下: //vite.config.js resolve: {// 绝对路径重命名 @/xxxx => src/xxxxalias: {"@": path.resolve(__dirname, "src"),

安全SCDN详解

随着互联网发展&#xff0c;越来越多的人都会使用到网站&#xff0c;个人网站、企业网站&#xff0c;各类大大小小的网站影响到人们的生活方方面面。许多站长都有使用或是听起过CDN&#xff0c;而SCDN&#xff0c;全称为“Security Content Delivery Network”&#xff0c;即安…

【Java设计模式】八、装饰者模式

文章目录 0、背景1、装饰者模式2、案例3、使用场景4、源码中的实际应用 0、背景 有个快餐店&#xff0c;里面的快餐有炒饭FriedRice 和 炒面FriedNoodles&#xff0c;且加配菜后总价不一样&#xff0c;计算麻烦。如果单独使用继承&#xff0c;那就是&#xff1a; 类爆炸不说&a…

【模板】AcWing795.《前缀和》(C++)

【题目描述】 输入一个长度为 n 的整数序列。 接下来再输入 m 个询问&#xff0c;每个询问输入一对 l,r。 对于每个询问&#xff0c;输出原序列中从第 l 个数到第 r 个数的和。 【输入格式】 第一行包含两个整数 n 和 m。 第二行包含 n 个整数&#xff0c;表示整数数列。 接下…

985硕的4家大厂实习与校招经历专题分享(part1)

先简单介绍一下我的个人经历&#xff1a; 985硕士24届毕业生&#xff0c;实验室方向:CV深度学习 就业&#xff1a;工程-java后端 关注大模型相关技术发展 校招offer: 阿里巴巴 字节跳动 等10 研究生期间独立发了一篇二区SCI 实习经历:字节 阿里 京东 B站 &#xff08;只看大厂…

非科班如何系统自学Python?

在数字化时代&#xff0c;Python如一位“全能选手”在编程语言的舞台上大放异彩&#xff0c;无论是数据科学、网站开发还是人工智能&#xff0c;它都能游刃有余地驾驭各种挑战。正因如此&#xff0c;越来越多的人渴望掌握这门兼具强大功能和优雅简洁的语言。 目录 引言 开始 …

ffmpeg 转码过程中参数含义

ffmpeg 转码过程中参数含义 frame 649 fps 73 q28.0 size 3072kB time00:00:25.88 bitrate 972.4kbits/ frame 694 fps 74 q28.0 size 3328kB time00:00:27.68 bitrate 984.9kbits/ frame 732 fps 74 q28.0 size 3584kB time00:00:29.20 bitrate1005.5kbits/ fram…

okHttp MediaType MIME格式详解

一、介绍 我们在做数据上传时&#xff0c;经常会用到Okhttp的开源库&#xff0c;okhttp开源库也遵循html提交的MIME数据格式。 所以我们经常会看到applicaiton/json这样的格式在传。 但是如果涉及到其他文件等就需要详细的数据格式&#xff0c;否则服务端无法解析 二、okHt…

【MySQL】数据库设计

目录 数据库设计基本任务 软件项目开发周期中数据库设计数据库设计的基本步骤解释需求分析需求分析的三个步骤&#xff1a;1.需求调查:2.分析数据字典内容定义数据的方法案例 3. 评审 概念结构设计概念模型概念结构设计E-R图概念模型组成元素&#xff1a;关系解释案例分析 逻辑…

深入解析缓存击穿及其高效应对策略

"缓存击穿"是缓存系统中的一个概念&#xff0c;指的是当缓存中没有要找的数据时&#xff0c;导致所有的请求都去查询数据库&#xff0c;如果这些请求都是对同一个数据项的查询&#xff0c;那么这就会导致数据库的压力骤增&#xff0c;从而影响系统的性能&#xff0c;…

【R包开发:入门】 简介+ 包的结构

简介 本书的目的是教你如何开发包&#xff0c;以便你可以写出自己的包&#xff0c;而不只是使用别人的包。 为什么要写一个包&#xff1f; 一个令人信服的理由是&#xff0c;你想要与他人分享代码。把你的代码打成一个包&#xff0c;可以方便他人使用&#xff0c;因为他们像你…

2024年 AI 辅助研发趋势

AI辅助是指人工智能&#xff08;AI&#xff09;技术被应用于辅助人们完成各种工作、任务或活动的过程。这种辅助可以包括提供智能建议、支持决策制定、自动化流程、增强人与机器之间的交互等。AI辅助通常旨在提高效率、减少人力成本、提升工作质量&#xff0c;并有助于拓展人类…

关于webpack种tree-sharking优化策略与sideEffect

再写项目时难免会出现部分代码写了却没有使用&#xff0c;代码量小没什么影响&#xff0c;但是当开发量多的时候&#xff0c;或是大量遗传代码叠加时&#xff0c;打包体积就会明显比较大。在webpack中可以使用tree-sharking进行代码优化。有两种代码优化策略tree-sharking(useE…