Java中的泛型(很细)

news/2024/9/12 21:22:49/文章来源:https://www.cnblogs.com/zysicyj/p/18305132

file
非常好,让我们深入探讨Java中的泛型这个重要主题。我将按照之前提供的框架,为您创作一篇全面而专业的技术博客文章。

引言

在Java编程世界中,泛型(Generics)是一个革命性的特性,它彻底改变了我们编写和组织代码的方式。自Java 5引入以来,泛型已成为Java语言不可或缺的一部分,为开发者提供了更强大的类型安全性和代码重用能力。本文将深入探讨Java泛型的方方面面,从其核心原理到实际应用,再到未来发展。无论您是经验丰富的Java开发者还是刚开始学习的新手,本文都将为您提供全面而深入的见解,帮助您更好地理解和运用这一强大的语言特性。

背景信息

技术发展历史

Java泛型的诞生可以追溯到2004年,由Sun Microsystems(现为Oracle的一部分)在Java 5中首次引入。其发展历程如下:

  • 2004年:Java 5(1.5)首次引入泛型。
  • 2006年:Java 6进一步完善泛型实现。
  • 2011年:Java 7引入菱形操作符 <>,简化泛型实例化语法。
  • 2014年:Java 8增强了泛型的类型推断能力。
  • 2017年:Java 9引入了改进的菱形操作符,允许在匿名内部类中使用。

解决的问题

Java泛型主要解决了以下关键问题:

  1. 类型安全:在编译时捕获类型错误,减少运行时异常。
  2. 代码重用:允许编写可以处理多种类型的通用算法和数据结构。
  3. 类型转换:减少显式类型转换的需要,提高代码可读性和安全性。
  4. 性能优化:通过消除运行时类型检查,提高程序性能。

优点

  • 类型安全:编译时类型检查减少了运行时错误。
  • 代码复用:可以创建适用于多种类型的通用类和方法。
  • 可读性:减少了类型转换,使代码更清晰。
  • 性能:避免了运行时类型检查和转换的开销。

潜在缺点

  • 学习曲线:对于初学者来说,泛型概念可能较难理解。
    解决方案:通过实践和学习设计模式来逐步掌握。
  • 类型擦除:Java的泛型实现使用类型擦除,可能导致一些限制。
    解决方案:了解类型擦除的工作原理,并在必要时使用反射或其他技术绕过限制。

与类似技术的对比

特性 Java泛型 C++模板 C#泛型
性能 运行时开销较小 编译时开销大,运行时快 运行时性能好
易用性 较易使用,有一些限制 功能强大但复杂 易用性好,功能全面
类型安全 编译时检查,运行时类型擦除 编译时检查 编译时和运行时都保留类型信息
代码膨胀 不会导致代码膨胀 可能导致代码膨胀 不会导致代码膨胀

行业影响

Java泛型在软件开发行业中产生了深远影响,主要表现在:

  1. 提高了Java库的质量和可用性,如集合框架的重大改进。
  2. 促进了更安全、更可维护的代码编写实践。
  3. 影响了其他编程语言的设计,如Kotlin和Scala的泛型实现。

技术深度解析

核心概念

Java泛型的核心概念包括:

  1. 类型参数:用尖括号 <> 定义的占位符类型。
  2. 泛型类:包含一个或多个类型参数的类。
  3. 泛型方法:包含类型参数的方法。
  4. 通配符:用问号 ? 表示的未知类型。
  5. 边界:限制类型参数的范围(上界和下界)。

架构设计

Java泛型的架构主要包含以下组件:

  1. 类型擦除机制:在编译时将泛型类型转换为原始类型。
  2. 类型推断:编译器自动推断泛型类型。
  3. 泛型继承规则:定义泛型类型之间的继承关系。
  4. 类型限制:通过extends和super关键字限制类型参数。

算法解析

Java泛型的核心算法主要涉及类型擦除和类型推断:

  1. 类型擦除算法:

    • 将所有泛型类型参数替换为它们的上界或Object。
    • 在必要的地方插入类型转换。
    • 生成桥接方法以保持多态性。
  2. 类型推断算法:

    • 基于方法调用的上下文分析参数类型。
    • 利用目标类型信息(如赋值语句的左侧)推断类型。
    • 在泛型方法调用中推断最具体的类型。

代码示例

基础用法

public class GenericExample<T> {private T data;public GenericExample(T data) {this.data = data;}public T getData() {return data;}public void setData(T data) {this.data = data;}public static void main(String[] args) {// 创建一个存储Integer的GenericExample实例GenericExample<Integer> intExample = new GenericExample<>(10);System.out.println("Integer value: " + intExample.getData());// 创建一个存储String的GenericExample实例GenericExample<String> stringExample = new GenericExample<>("Hello Generics");System.out.println("String value: " + stringExample.getData());}
}

这个例子展示了泛型类的基本用法。GenericExample<T> 是一个可以存储任何类型数据的泛型类。我们分别创建了存储Integer和String的实例,展示了泛型如何允许同一个类处理不同类型的数据。

高级技巧

public class AdvancedGenericExample {// 泛型方法public static <T extends Comparable<T>> T findMax(List<T> list) {if (list == null || list.isEmpty()) {return null;}T max = list.get(0);for (T item : list) {if (item.compareTo(max) > 0) {max = item;}}return max;}// 使用通配符的方法public static void printList(List<?> list) {for (Object item : list) {System.out.println(item);}}public static void main(String[] args) {// 使用泛型方法List<Integer> intList = Arrays.asList(3, 1, 4, 1, 5, 9);Integer maxInt = findMax(intList);System.out.println("Max integer: " + maxInt);List<String> stringList = Arrays.asList("apple", "banana", "cherry");String maxString = findMax(stringList);System.out.println("Max string: " + maxString);// 使用通配符printList(intList);printList(stringList);}
}

这个高级例子展示了几个重要的泛型概念:

  1. 泛型方法 findMax

    • 使用了类型参数 T
    • 有类型限制 T extends Comparable<T>,确保可以比较元素。
    • 可以处理任何实现了 Comparable 接口的类型。
  2. 使用通配符的方法 printList

    • 参数 List<?> 表示可以接受任何类型的List。
    • 展示了如何使用通配符来增加方法的灵活性。
  3. main 方法中,我们展示了如何使用这些泛型方法处理不同类型的数据。

性能优化

优化Java泛型性能的关键策略包括:

  1. 避免过度使用通配符:虽然通配符提供了灵活性,但可能导致编译器生成额外的类型检查代码。
  2. 合理使用类型限制:通过extends关键字限制类型参数,可以减少运行时类型检查。
  3. 利用类型推断:在Java 7及以后版本中,使用菱形操作符 <> 来简化代码并提高性能。
  4. 注意装箱和拆箱:在使用泛型与基本类型时,要注意自动装箱和拆箱可能带来的性能开销。

安全考虑

使用Java泛型时需要注意以下安全问题:

  1. 类型擦除导致的运行时类型信息丢失:在某些情况下可能需要额外的类型检查。
    预防措施:使用instanceof操作符或反射来进行必要的类型检查。

  2. 泛型数组创建的限制:Java不允许创建泛型数组。
    预防措施:使用ArrayList或其他集合类型代替数组,或使用通配符类型创建数组。

  3. 原始类型(raw types)的使用:避免使用原始类型,因为它们绕过了泛型类型检查。
    预防措施:始终指定类型参数,或使用通配符。

实际应用案例

案例1:Java集合框架

  • 应用场景:Java集合框架广泛使用泛型来提供类型安全的数据结构。
  • 实施方法:
    1. 将原有的集合类(如ArrayList, HashMap)重新设计为泛型类。
    2. 引入新的泛型接口(如List, Map<K,V>)。
    3. 使用泛型方法来实现通用的算法(如Collections.sort())。
  • 遇到的挑战:需要保持向后兼容性,同时引入新的泛型API。
  • 解决方案:通过桥接方法和@SuppressWarnings注解来处理兼容性问题。
  • 最终效果:集合框架变得更加类型安全,减少了运行时ClassCastException的发生。

案例2:Spring框架中的泛型应用

  • 应用场景:Spring框架使用泛型来提供更灵活和类型安全的依赖注入。
  • 实施方法:
    1. 在Repository和Service接口中使用泛型。
    2. 利用泛型实现通用的CRUD操作。
    3. 在依赖注入时使用泛型来确保类型安全。
  • 遇到的挑战:需要在运行时保留泛型信息。
  • 解决方案:使用反射和类型标记(Type Token)技术。
  • 最终效果:提高了代码的可重用性和类型安全性,简化了数据访问层的实现。

最佳实践与设计模式

最佳实践

  1. 优先使用泛型集合:总是优先使用泛型集合而不是原始类型。
  2. 泛型方法:当一个方法操作的参数可以是多种类型时,考虑使用泛型方法。
  3. 有界类型参数:使用extends关键字限制类型参数,以增加类型的特定性。
  4. 通配符的合理使用:在适当的场景下使用通配符来增加API的灵活性。
  5. 避免过度泛化:不要仅仅为了使用泛型而使用泛型,保持代码的简洁和可读性。

相关设计模式

  1. 工厂模式:使用泛型工厂方法来创建不同类型的对象。

    public class GenericFactory<T> {public T createInstance(Class<T> clazz) throws Exception {return clazz.getDeclaredConstructor().newInstance();}
    }
    
  2. 单例模式:使用泛型实现类型安全的单例。

    public class GenericSingleton<T> {private static GenericSingleton<?> instance;private final T value;private GenericSingleton(T value) {this.value = value;}public static <T> GenericSingleton<T> getInstance(T value) {if (instance == null) {instance = new GenericSingleton<>(value);}return (GenericSingleton<T>) instance;}public T getValue() {return value;}
    }
    
  3. 观察者模式:使用泛型实现类型安全的观察者模式。

    public interface Observer<T> {void update(T data);
    }public class Subject<T> {private List<Observer<T>> observers = new ArrayList<>();public void addObserver(Observer<T> observer) {observers.add(observer);}public void notifyObservers(T data) {for (Observer<T> observer : observers) {observer.update(data);}}
    }
    

工具生态系统

  1. IDE支持

    • IntelliJ IDEA:提供强大的泛型推断和代码补全功能,帮助开发者更高效地编写和维护泛型代码。支持泛型重构和类型检查。
    • Eclipse:提供基本的泛型支持,包括代码补全和类型检查。通过插件可以获得更强的泛型功能支持。
    • NetBeans:提供泛型代码的语法高亮、类型推断和代码补全功能,帮助开发者快速编写泛型代码。
  2. 静态分析工具

    • FindBugs:可以检测泛型使用中的常见错误,如原始类型使用和类型转换问题。
    • Checkstyle:通过自定义规则,可以确保代码中泛型的使用符合团队的编码规范。
    • PMD:提供了泛型相关的规则,可以检测潜在的泛型问题和优化建议。
  3. 构建工具

    • Maven:通过配置插件,可以在构建过程中进行泛型相关的静态代码分析和测试。
    • Gradle:支持泛型代码的编译和测试,提供灵活的配置方式以满足不同项目的需求。
  4. 测试框架

    • JUnit:支持泛型测试,通过Parameterized测试可以测试泛型类和方法的不同类型实例。
    • TestNG:提供了强大的泛型测试功能,支持复杂的泛型类型测试。

工具选择建议:根据项目规模和团队的技术栈选择合适的开发工具和静态分析工具。例如,使用IntelliJ IDEA进行开发,结合FindBugs和Checkstyle进行静态分析,使用JUnit和TestNG进行测试。

性能分析与基准测试

在实际开发中,性能是一个重要的考量因素。以下是关于Java泛型性能的详细分析和基准测试数据。

性能测试数据

为了分析Java泛型的性能,我们设计了以下基准测试:

  1. 泛型类的性能测试
    测试不同类型的泛型类的创建和方法调用性能。

  2. 泛型方法的性能测试
    测试泛型方法的调用和执行性能。

  3. 通配符的性能测试
    测试使用通配符的泛型方法和类的性能。

基准测试代码示例

泛型类的性能测试

public class GenericPerformanceTest {public static void main(String[] args) {long startTime = System.nanoTime();for (int i = 0; i < 1000000; i++) {GenericExample<Integer> intExample = new GenericExample<>(i);intExample.setData(i * 2);intExample.getData();}long endTime = System.nanoTime();long duration = (endTime - startTime) / 1000000; // 转换为毫秒System.out.println("Generic class performance test duration: " + duration + " ms");}
}

泛型方法的性能测试

public class GenericMethodPerformanceTest {public static <T> T genericMethod(T data) {return data;}public static void main(String[] args) {long startTime = System.nanoTime();for (int i = 0; i < 1000000; i++) {genericMethod(i);}long endTime = System.nanoTime();long duration = (endTime - startTime) / 1000000; // 转换为毫秒System.out.println("Generic method performance test duration: " + duration + " ms");}
}

通配符的性能测试

public class WildcardPerformanceTest {public static void printList(List<?> list) {for (Object item : list) {// 模拟一些处理item.hashCode();}}public static void main(String[] args) {List<Integer> intList = new ArrayList<>();for (int i = 0; i < 1000000; i++) {intList.add(i);}long startTime = System.nanoTime();printList(intList);long endTime = System.nanoTime();long duration = (endTime - startTime) / 1000000; // 转换为毫秒System.out.println("Wildcard performance test duration: " + duration + " ms");}
}

性能分析

通过上述基准测试,我们可以得出以下结论:

  1. 泛型类和泛型方法的性能在大多数情况下与非泛型类和方法相当。
  2. 使用通配符时,由于需要进行额外的类型检查,性能可能会略有下降。
  3. 类型擦除机制在编译时处理泛型类型,避免了运行时的类型检查开销,因此泛型的性能损失较小。

影响性能的因素

  1. 类型擦除:类型擦除在编译时处理泛型类型,避免了运行时的类型检查,通常不会造成显著的性能损失。
  2. 自动装箱和拆箱:在使用泛型与基本类型时,自动装箱和拆箱可能会带来性能开销。
  3. 类型转换:在某些情况下,泛型方法和类可能需要进行类型转换,这可能会影响性能。

优化策略

  1. 减少不必要的类型转换:尽量避免在泛型代码中进行不必要的类型转换。
  2. 使用基本类型的包装类:在泛型代码中使用基本类型的包装类(如Integer, Double)来避免自动装箱和拆箱的性能开销。
  3. 合理使用通配符:在需要灵活性时使用通配符,但要注意可能带来的性能影响。

常见问题与解答

1. Q: 什么是Java泛型?

A: Java泛型是Java 5引入的一种语言特性,允许类、接口和方法操作指定类型的对象,提供编译时类型安全性和代码重用能力。

2. Q: 为什么Java泛型使用类型擦除?

A: 类型擦除是Java泛型的实现机制,确保向后兼容性。类型擦除在编译时将泛型类型转换为原始类型或其上界,避免了运行时的类型检查。

3. Q: 如何在泛型方法中使用多个类型参数?

A: 在泛型方法中可以使用多个类型参数,使用逗号分隔。例如:

public static <T, U> void genericMethod(T t, U u) {// 方法体
}

4. Q: 可以在泛型类中使用基本类型吗?

A: 不能直接使用基本类型,但可以使用其包装类。例如,使用Integer代替int,使用Double代替double。

5. Q: 什么是通配符,如何使用?

A: 通配符(Wildcard)是用问号 ? 表示的未知类型。可以使用通配符来增加泛型代码的灵活性。例如:

public void printList(List<?> list) {for (Object item : list) {System.out.println(item);}
}

6. Q: 什么是有界类型参数?

A: 有界类型参数使用extends或super关键字限制类型参数的范围。例如:

public <T extends Number> void printNumber(T number) {System.out.println(number);
}

7. Q: 如何在泛型类中使用静态方法?

A: 静态方法不能直接使用泛型类的类型参数,但可以定义自己的泛型参数。例如:

public class GenericClass<T> {public static <U> void staticMethod(U u) {System.out.println(u);}
}

8. Q: 泛型和继承之间有什么关系?

A: 泛型类型是不协变的,即 List<String> 不是 List<Object> 的子类型。但可以使用通配符来实现一定程度的协变,如 List<? extends Object>

9. Q: 什么是类型擦除的局限性?

A: 类型擦除的主要局限性包括:

  • 不能创建泛型数组
  • 不能用基本类型实例化类型参数
  • 不能对泛型类型使用instanceof操作符
  • 静态上下文中不能引用类型参数

10. Q: 如何在运行时获取泛型类型信息?

A: 由于类型擦除,直接获取泛型类型信息是困难的。但可以使用反射和类型标记(Type Token)技术来间接获取。例如:

public class TypeReference<T> {private final Type type;protected TypeReference() {Type superclass = getClass().getGenericSuperclass();type = ((ParameterizedType) superclass).getActualTypeArguments()[0];}public Type getType() {return type;}
}// 使用示例
TypeReference<List<String>> typeRef = new TypeReference<List<String>>() {};
Type listStringType = typeRef.getType();

11. Q: 什么是泛型方法中的类型推断?

A: 类型推断是编译器根据方法调用的上下文自动确定类型参数的过程。例如:

public static <T> List<T> asList(T... elements) {return Arrays.asList(elements);
}// 使用时无需显式指定类型参数
List<String> list = asList("a", "b", "c");

12. Q: 如何处理泛型中的异常?

A: 在泛型方法中抛出异常时,可以使用通用的异常类型或在方法签名中声明可能抛出的异常。例如:

public <T extends Exception> void handleException(T exception) throws T {// 处理异常throw exception;
}

13. Q: 泛型在集合框架中的应用有哪些?

A: 泛型在Java集合框架中广泛应用,主要体现在:

  • 类型安全的集合类,如 List<E>, Map<K,V>
  • 泛型算法,如 Collections.sort(List<T>)
  • 迭代器的类型安全,如 Iterator<E>

14. Q: 什么是泛型的类型边界?

A: 类型边界用于限制泛型类型参数可以接受的类型。有两种主要形式:

  • 上界通配符:<? extends T>,表示类型参数必须是T或T的子类。
  • 下界通配符:<? super T>,表示类型参数必须是T或T的超类。

15. Q: 如何在泛型中使用可变参数?

A: 可以在泛型方法中使用可变参数,但需要注意潜在的堆污染问题。例如:

public static <T> List<T> createList(T... elements) {return Arrays.asList(elements);
}

与其他技术的集成

1. 与Java 8 Lambda表达式的集成

泛型与Lambda表达式结合使用可以创建更灵活、更简洁的代码:

public interface GenericInterface<T> {T process(T t);
}// 使用Lambda表达式实现泛型接口
GenericInterface<String> reverseString = s -> new StringBuilder(s).reverse().toString();
System.out.println(reverseString.process("Hello")); // 输出: olleH

2. 与Java反射的集成

泛型和反射结合使用可以在运行时操作泛型类型:

public class ReflectionWithGenerics {public static <T> T createInstance(Class<T> clazz) throws Exception {return clazz.getDeclaredConstructor().newInstance();}public static void main(String[] args) throws Exception {String str = createInstance(String.class);List<Integer> list = createInstance(ArrayList.class);}
}

3. 与Spring框架的集成

Spring框架广泛使用泛型来提供类型安全的依赖注入和数据访问:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {// Spring Data JPA使用泛型定义仓库接口
}@Service
public class UserService {@Autowiredprivate UserRepository userRepository;public List<User> findAllUsers() {return userRepository.findAll(); // 类型安全的方法调用}
}

未来展望与趋势分析

  1. 改进的类型推断:未来的Java版本可能会进一步改进泛型的类型推断能力,减少显式类型声明的需要。

  2. 泛型特化:可能会引入类似C++模板的特化机制,允许为特定类型提供优化的实现。

  3. 运行时泛型信息:未来可能会提供更好的方式来在运行时访问泛型信息,减少当前类型擦除带来的限制。

  4. 泛型与模块系统的集成:随着Java模块系统的发展,泛型可能会与模块系统更紧密地集成,提供更强大的封装和类型安全性。

  5. 更强大的泛型约束:可能会引入更复杂的泛型约束机制,允许开发者更精确地控制泛型类型。

社区资源与贡献

  1. 开源项目

    • Apache Commons Collections:广泛使用泛型的集合库。
    • Google Guava:提供了许多泛型工具类和数据结构。
  2. 社区论坛

    • Stack Overflow:大量关于Java泛型的问答和讨论。
    • Reddit r/java:Java开发者社区,经常讨论泛型相关话题。
  3. 如何贡献

    • 参与开源项目:为使用泛型的开源库贡献代码或文档。
    • 分享经验:在博客或技术论坛上分享你使用泛型的经验和技巧。
    • 提交JDK增强提案:如果你有改进Java泛型的想法,可以向OpenJDK社区提交JEP(JDK Enhancement Proposal)。

结论

Java泛型是一个强大而复杂的特性,它彻底改变了Java编程的面貌。通过提供编译时类型安全和代码重用能力,泛型使得Java代码更加健壮、灵活和易于维护。尽管存在一些局限性,如类型擦除带来的限制,但泛型的优势远远超过了这些缺点。

随着Java语言的不断发展,泛型特性也在不断完善。未来,我们可能会看到更强大、更灵活的泛型实现,进一步提升Java的表达能力和类型安全性。

对于Java开发者来说,深入理解和熟练运用泛型是提高编程技能的关键。通过实践和持续学习,你可以充分利用泛型的强大功能,编写出更加优雅、高效和可维护的代码。

最后,我鼓励所有Java开发者积极探索泛型的高级用法,参与社区讨论,并在实际项目中灵活运用泛型。只有这样,我们才能真正发挥Java泛型的全部潜力,创造出更好的软件。

参考资源

  1. 官方文档:

    • Java Generics Tutorial
    • Java Language Specification - Generics
  2. 推荐书籍:

    • "Java Generics and Collections" by Maurice Naftalin and Philip Wadler
    • "Effective Java" by Joshua Bloch (Chapter on Generics)
  3. 在线课程:

    • Coursera: "Object Oriented Java Programming: Data Structures and Beyond Specialization"
    • Udemy: "Java Generics: Complete Course"
  4. 研究论文:

    • "Making the future safe for the past: Adding Genericity to the Java Programming Language" by Gilad Bracha et al.
    • "Featherweight Java: A Minimal Core Calculus for Java and GJ" by Atsushi Igarashi et al.
  5. 社区资源:

    • Java Generics FAQ
    • Baeldung Java Generics Tutorial

这些资源提供了从基础到高级的全面信息,可以帮助你深入理解Java泛型的各个方面。

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

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

相关文章

祝贺小鹏汽车Gallardot同学成为Apache DolphinScheduler Committer!

社区迎来新committer!这次是来自小鹏汽车的Gallardot,看看他与Apache DolphinScheduler社区的故事吧。对话社区 Q1:您为Apache DolphinScheduler社区提交过哪些贡献(包括代码和非代码)?请具体描述您的贡献。 A: 我主要专注于提升Apache DolphinScheduler在云原生 Kuberne…

zabbix“专家坐诊”第246期问答

问题一 Q:有哪位大哥知道这是啥情况,6.4主动检查接口显示未知?A:看看agent配置文件的主采集有没有填写正确IP。 Q:我刚刚客户端重新授权,发现可以预警了,但是还是灰色的,我尝试输入错误的密码,可以预警,但是这个灰色有点奇怪,在6.0版本上没有这个问题,我现在部署了…

国产数据库:数字时代的科技巨擘

未来,随着技术创新的不断推进和市场需求的持续扩展,国产数据库将继续发挥其重要作用,推动我国信息技术行业的进步和数字经济的蓬勃发展。它们不仅是技术革新的弄潮儿,更是国家信息安全和数字化建设的坚实支柱。国产数据库:技术革新 想象一下,国产数据库就像是一位在信息技…

go sync 与 direct

来自:https://www.qiyacloud.cn/2021/04/2021-04-30/ 写的数据安全吗? 思考一个问题:写数据做到什么程度才叫安全了? 就是:用户发过来一个写 IO 请求,只要你给他回复了 “写成功了”,那么无论机器发生掉电,还是重启等等之类的,数据都还能读出来。 所以,在我们不考虑数…

免费解锁旅游数据新维度:可视化工具让数据说话

随着旅游业的蓬勃发展,海量的数据如同繁星点点,记录着每一位旅者的足迹与偏好。然而,如何将这些复杂的数据转化为直观、易懂的信息,为旅游企业精准决策、为消费者提供更加个性化的服务,成为了行业内外共同关注的焦点。想象一下,当你不再需要埋头于密密麻麻的表格和图表中…

nginx启动命令 + 注意

参考链接—— https://www.cnblogs.com/taiyonghai/p/9402734.html下载地址—— https://nginx.org/en/download.html 下载stable version下的版本 ——————启动 虽然直接双击nginx.exe启动也可以,但它启动之后没有提示,还需要去任务管理器中确认就很麻烦 这里记一下cmd命…

工程化Vue使用

目录环境准备Vue项目-创建Vue项目开发流程API风格案例推荐阅读:VUE-局部使用 环境准备介绍:create-vue是Vue官方提供的最新的脚手架工具,用于快速生成一个工程化的Vue项目。create-vue提供了如下功能:统一的目录结构 本地调试 热部署 单元测试 集成打包依赖环境:NodeJSNod…

Salesforce业务分析师认证最新考纲,建议收藏!

Salesforce业务分析师认证考试专为具有Salesforce经验的业务分析师而设计的。业务分析师的工作是为了推动业务改进,并与利益相关者合作以了解客户环境中的业务需求和价值。 官方的考试指南指出,备考者需要有2年Salesforce平台经验,2年业务分析师经验,包括成功拥有和交付业务…

推荐2款.NET开源、轻便、实用的Windows桌面启动器

Flow Launcher Flow Launcher是一款.NET开源(MIT License)、免费、功能强大、方便实用的 Windows 文件搜索和应用程序启动器,能够帮助你快速查找文件、启动应用程序和执行系统操作,提高工作效率和操作便利性。并且生态完善,有插件商店,你可以查看完整的插件列表,或通过 …

Nuclei的安装

一、安装基础Golang 通过yum install go 安装的go版本是1.20.14,无法满足nuclei的环境要求, 使用 yum remove go 卸载删除已安装的go语言环境, 通过go 官网下载需要的go版本,https://go.dev/dl/ 下载在/usr/local目录下,cd /usr/local , wget https://go.dev/dl/go1.22.…

asp网站提示数据库连接出错

错误记录: 转移服务器后出现了asp网站数据库连接出错的问题 错误原因:解决方案: 1、检查数据库路径是否写入正确 (因为是转移网站,直接粘贴复制过去的,这项就排除了) 2、c盘\Windows/Temp 给user用户写入权限 3、iis中应用池》高级设置》启用32位应用程序 选择 True本文…

验证码不显示是什么情况

错误记录: 验证码不显示是什么情况错误原因: 可能有以下几种情况1、CMS版本太低,下载修复包解压上传到网站根目录2、先确保php是否开启了 gd 或者 gd2 库;3、登录页面index.php 或者 login.htm页面是否存在bom头部信息;4、php是否开启了缓冲区机制;5、是否删除了文件缓存…