【Java高级语法】(三)泛型:关于泛型最全面的讲解来了~

news2024/11/26 18:22:38

Java高级语法详解之泛型

  • :one: 概念
  • :two: 优势
  • :three: 使用
    • 3.1 泛型类
    • 3.2 泛型接口
    • 3.3 泛型方法
  • :four: 通配符(Wildcards)
    • 4.1 无界通配符(Unbounded Wildcard)
    • 4.2 上限通配符(Upper Bounded Wildcard)
    • 4.3 下限通配符(Lower Bounded Wildcard)
  • :five: 类型擦除(Type Erasure)
  • :six: 泛型对协变和逆变的支持
  • :seven: 应用场景
  • :ear_of_rice: 总结
  • :bookmark_tabs: 本文源码下载地址

1️⃣ 概念

Java 编程语言在 JDK 5.0 版本中引入了泛型(Generics)的概念,以增加源代码的类型安全性和可读性。泛型允许类、接口和方法在定义时使用一个或多个类型参数,使得它们可以在编译时具有更强的类型检查,并且能够避免类型转换错误。

泛型的核心思想是参数化类型(Parameterized Type)。通过在类、接口或方法的定义中使用类型参数,我们可以创建一种“模板”,这个模板可以用于不同的数据类型,并在编译时进行类型检查。这个类型参数可以在实例化的时候指定具体的类型,从而实现类型安全。

2️⃣ 优势

使用泛型的主要优势是提供了类型安全和可读性方面的好处:

  • 类型安全:使用泛型可以在编译时捕获类型错误。通过在编译时对传递给泛型容器或方法的元素类型进行检查,可以避免在运行时发生意外的 ClassCastException
  • 可读性:通过明确指定类型参数,可以使代码更易读和理解。方法或类命名更清晰,并且减少了需要对类型进行注释或文档说明的情况;
  • 代码复用:泛型可以使用相同的类型安全体系来操作多种不同类型的数据,从而提高代码的可重用性;
  • 简化开发:使用泛型可以减少冗余的类型转换代码,提供更简洁和优雅的编程方式;
  • 错误检测:泛型使得编译器能够在编译时对代码进行更严格的类型检查,减少错误的产生,并会提供更精确的错误提示。

3️⃣ 使用

3.1 泛型类

在Java中,我们可以创建泛型类和泛型接口。泛型类和泛型接口的定义方式与普通类和接口相似,只是在名称后面加上一对尖括号(<>)并在其中指定类型参数。

下面是一个简单的示例,展示了如何定义一个泛型类:

public class Box<T> {
    private T value;

    public void setValue(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }
    
    @Override
    public String toString() {
        return "Box{" +
                "value=" + value +
                '}';
    }
}

在这个示例中,Box 是一个泛型类,类型参数 T 被放置在类名后的尖括号中。在类内部,我们可以使用类型参数 T 来声明成员变量和方法的类型,并在实例化时指定具体的类型。

以下是使用该泛型类的使用示例:

public class GenericClassDemo {

    public static void main(String[] args) {
        Box<Integer> integerBox = new Box<>();
        integerBox.setValue(10);
        System.out.println(integerBox);

        Box<String> stringBox = new Box<>();
        stringBox.setValue("hello");
        System.out.println(stringBox);
    }
}

通过在实例化 Box 类时指定了具体的类型参数,我们可以创建不同类型的 Box 实例,并将不同类型的值存储在其中。

输出结果:

Box{value=10}
Box{value=hello}

3.2 泛型接口

下面是一个简单的示例,定义了一个泛型接口Container<T>,其中T表示泛型类型参数。接口中有两个方法:addItem用于添加一个元素到容器中,getItem用于获取容器中的元素:

public interface Container<T> {
    void addItem(T[] item);  // 添加一组元素到容器中
    T[] getItem();           // 获取容器中的元素
}

以下是一个实现了该泛型接口的具体类Box<T>,该类通过实现接口的方式来定义接口中的方法:

import java.util.Arrays;

// 实现泛型接口
public class Box<T> implements Container<T> {
    private T[] item;

    public void addItem(T[] item) {
        this.item = item;
    }

    public T[] getItem() {
        return item;
    }

    @Override
    public String toString() {
        return "Box{" +
                "item=" + Arrays.toString(item) +
                '}';
    }
}

以下是使用该泛型接口的使用示例:

public class GenericsInterfaceDemo {

    public static void main(String[] args) {
        // 使用泛型接口
        Container<String> container1 = new Box<>();
        container1.addItem(new String[]{"Hello","world"});
        System.out.println(container1);

        Container<Integer> container2 = new Box<>();
        container2.addItem(new Integer[]{42,36});
        System.out.println(container2);
    }
}

main函数中,我创建了两个泛型容器对象container1container2,分别使用了泛型实参StringInteger。然后,调用addItem方法将一组元素添加到容器中,最后,将容器对象的元素进行打印输出。

运行结果:

Box{item=[Hello, world]}
Box{item=[42, 36]}

3.3 泛型方法

除了在类和接口级别上定义泛型之外,Java 还允许在单独的方法中使用泛型。这被称为泛型方法(Generic Method)。

下面是一个简单的示例,展示了如何定义泛型方法:

public class ArrayUtils {
    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.print(element + " ");
        }
        System.out.println();
    }
}

使用泛型方法:

public class GenericMethodDemo {
    public static void main(String[] args) {
        // 使用泛型方法
        Integer[] intArray = {1, 2, 3, 4, 5};
        ArrayUtils.printArray(intArray);

        String[] strArray = {"Hello", "World"};
        ArrayUtils.printArray(strArray);
    }
}

在这个示例中,printArray 是一个泛型方法。类型参数 T 被放置在方法的返回类型之前的尖括号中,它表示任意类型。通过在调用泛型方法时传递相应的实际参数类型,编译器会对数组进行相应的类型检查,并执行相应的方法体。

运行结果:

1 2 3 4 5 
Hello World 

4️⃣ 通配符(Wildcards)

在泛型中,可以使用通配符来表示一组类型。通配符允许我们在泛型代码中处理不同类型的参数。

Java 提供了三种通配符:? 无界通配符(Unbounded Wildcard)、? extends T 上限通配符(Upper Bounded Wildcard)和 ? super T 下限通配符(Lower Bounded Wildcard)。

  • 无界通配符(?):用于表示未知类型。例如,List<?> 表示一个具有未知元素类型的列表;
  • 上限通配符(? extends T):用于限制传入的类型必须是某个类或其子类。例如,List<? extends Number> 表示一个元素类型是 Number 或其子类的列表;
  • 下限通配符(? super T):用于限制传入的类型必须是某个类或其父类。例如,List<? super Integer> 表示一个元素类型是 Integer 或其父类的列表。

4.1 无界通配符(Unbounded Wildcard)

无界通配符(?) 允许我们对未知类进行操作,并在类型安全的前提下进行编码。

以下是一个示例,展示了如何使用无界通配符:

import java.util.ArrayList;
import java.util.List;

//一个使用了泛型的无界通配符的演示程序
public class UnboundedWildcardDemo {

    static class Animal {
        public void makeSound() {
            System.out.println("Animal is making a sound");
        }
    }

    static class Dog extends Animal {
        public void makeSound() {
            System.out.println("Dog is barking");
        }
    }

    public static void main(String[] args) {
        List<Animal> animals = new ArrayList<>();
        animals.add(new Animal());
        animals.add(new Dog());

        // 定义一个使用无界通配符的List
        List<?> wildcardList = animals;

        // 使用无界通配符迭代列表并调用方法
        for (Object animal : wildcardList) {
            // 由于通配符类型未知,只能调用Object上定义的方法
            System.out.println(animal.toString());
        }
    }

}

在这个例子中,我定义了一个Animal类和一个继承自AnimalDog类。然后创建了一个ArrayList来存储Animal对象和Dog对象。

接下来,使用无界通配符(?)定义了另一个列表wildcardList,将其指向之前创建的animals列表。这意味着可以将任何类型的列表赋值给wildcardList,而不仅仅是List<Animal>

在循环中,通过迭代wildcardList中的元素来调用它们的toString()方法。由于无界通配符的类型未知,只能将迭代出的元素视为Object。在本例中,输出结果将是每个对象的默认toString()实现。

运行结果:

com.xiaoshan.unboundedwildcard.UnboundedWildcardDemo$Animal@1b6d3586
com.xiaoshan.unboundedwildcard.UnboundedWildcardDemo$Dog@4554617c

4.2 上限通配符(Upper Bounded Wildcard)

上限通配符(? extends T):用于限制传入的类型必须是某个类T 或其子类。

以下是一个示例,展示了如何使用上限通配符:

import java.util.Arrays;
import java.util.List;

public class UpperBoundedWildcardDemo {
    public static double sum(List<? extends Number> numbers) {
        double total = 0;
        for (Number number : numbers) {
            total += number.doubleValue();
        }
        return total;
    }

    public static void main(String[] args) {
        List<Integer> integers = Arrays.asList(1, 2, 3);
        double result = sum(integers);
        System.out.println(result);

        List<Double> doubles = Arrays.asList(1.5, 2.2, 3.82);
        result = sum(doubles);
        System.out.println(result);
    }
}

在这个示例中,sum 方法使用上限通配符(? extends Number),它允许方法接受继承自 Number 的子类的列表作为参数,例如 IntegerDouble,使得支持多种数字类型的运算。在方法内部,通过迭代遍历列表中的每个元素,将其转换为 double 类型并累加到变量 total 上。最后,返回 total 的值。
通过扩展泛型方法的灵活性,可以将不同类型的列表传递给 sum 方法,并对其进行求和操作。

运行结果:

6.0
7.52

4.3 下限通配符(Lower Bounded Wildcard)

下限通配符(? super T):用于限制传入的类型必须是某个类或其父类。

以下是一个示例,展示了如何使用下限通配符。
首先定义两个类FruitAppleFruit是一个父类,AppleFruit的子类。

public class Fruit {

    private String info = "一个水果";

    @Override
    public String toString() {
        return "Fruit{" +
                "info='" + info + '\'' +
                '}';
    }

}

class Apple extends Fruit {

    private String info = "一个苹果";

    @Override
    public String toString() {
        return "Apple{" +
                "info='" + info + '\'' +
                '}';
    }
}

然后以下程序展示了Java中下界通配符的使用:

import java.util.Arrays;
import java.util.List;

public class LowerBoundedWildcardDemo {
    public static void printf(List<? super Apple> list) {
        System.out.println(list);
    }

    public static void main(String[] args) {
        List<Apple> appleList = Arrays.asList(new Apple(), new Apple());
        printf(appleList);

        List<Fruit> fruitList = Arrays.asList(new Fruit(), new Fruit());
        printf(fruitList);
    }
}

静态方法printf的参数是一个类型为 List<? super Apple> 的列表,这个列表可以接受任何类型为Apple及其父类的列表。 然后只简单地打印了传递给方法的列表。

main方法中,首先创建了一个List<Apple>对象appleList并将其初始化为包含两个Apple对象的数组的列表。然后,调用printf方法并将appleList作为参数传递给它。由于参数类型为List<Apple>,而printf方法接受的参数类型为List<? super Apple>,所以这个调用是合法的。

接下来,创建了一个List<Fruit>对象fruitList并将其初始化为包含两个Fruit对象的数组的列表。然后,再次调用printf方法并将fruitList作为参数传递给它。由于FruitApple的父类,所以这个调用仍然是合法的。

运行结果:

[Apple{info='一个苹果'}, Apple{info='一个苹果'}]
[Fruit{info='一个水果'}, Fruit{info='一个水果'}]

5️⃣ 类型擦除(Type Erasure)

Java 的泛型实现使用了类型擦除机制。这意味着泛型的类型信息只存在于代码编译阶段,在运行时会被擦除掉。类型擦除是为了实现与之前版本的 Java 兼容,并且可以在运行时提高性能。

由于类型擦除,泛型类型参数在运行时会被擦除为它们的原始类型或限定类型。例如,一个泛型类在运行时会变成它的原始形式。这就是为什么无法在运行时获得泛型类型参数的具体类型。

以下是一个示例,展示了类型擦除的效果:

public class TypeErasureDemo<T> {
    private T value;

    public void setValue(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }

    public static void main(String[] args) {
        // 使用类型擦除
        TypeErasureDemo<String> example = new TypeErasureDemo<>();
        example.setValue("Hello");
        // 返回类型为 String
        String value = example.getValue();
        System.out.println(value);
        // 返回类型为 TypeErasureDemo,而不是 TypeErasureDemo<String>
        Class<? extends TypeErasureDemo> clazz = example.getClass();
        System.out.println(clazz);
    }
}

在这个示例中,GenericExample 是一个泛型类。虽然我在实例化 GenericExample 时指定了具体的类型参数(String),但是在运行时通过调用 example.getClass() 来获取其类对象时,,返回的类型是 GenericExample,而不是 GenericExample<String>。这说明在运行时,泛型类型参数会被擦除为其原始类型。

运行结果:

Hello
class com.xiaoshan.typeerasure.TypeErasureDemo

尽管在运行时无法获得泛型类型参数的具体类型信息,但是可以通过反射来获取泛型类或方法的基本信息。通过反射,可以获取泛型类的属性、方法和接口等,并进一步操作它们。

6️⃣ 泛型对协变和逆变的支持

需要注意的是,泛型在存在子类型关系时有一些特殊的规则:

  • 泛型不支持协变:即使 SubSuper 的子类,Container<Sub> 也不是 Container<Super> 的子类型;
  • 泛型不支持逆变:即使 SuperSub 的子类,Container<Super> 也不是 Container<Sub> 的父类型。
  • 泛型可以使用上限通配符(? extends T)模拟协变,使用下限通配符(? super T)模拟逆变。

🔍 协变(covariant)和逆变(contravariant)是什么?

协变和逆变是类型系统中的概念,用于描述类型之间的替换关系。

协变指的是在一种类型替换另一种类型时,被替换的类型(通常称为子类型或窄类型)可以是原始类型(通常称为父类型或宽类型)的子类型。换句话说,当你需要一个特定类型的对象时,你可以使用它的子类型作为替代,且不会引发任何错误。

逆变则是相反的概念-指的是当一个类型替换另一个类型时,被替换的类型可以是原始类型的父类型。换句话说,在需要特定类型的地方,可以使用其父类型的实例而不会导致错误。

总结起来,协变描述了窄类型(子类型)替换宽类型(父类型),而逆变则描述了宽类型(父类型)替换窄类型(子类型)。在类型系统中,这些概念有助于确保类型安全和灵活性,允许我们在使用类型的地方传递更具体或更一般化的类型对象。

以下是一个示例,展示了这些规则的应用:

import java.util.ArrayList;
import java.util.List;

public class InvarianceDemo{
    static class Super {
        @Override
        public String toString() {
            return "Super{}";
        }
    }
    static class Sub extends Super {
        @Override
        public String toString() {
            return "Sub{}";
        }
    }

    public static void test1() {
        // 1、不支持协变
        // 编译不通过:Required type: List <Super>. Provided: ArrayList <Sub>
        List<Super> superList1 = new ArrayList<Sub>();

        // 编译不通过:Required type: List <Super>. Provided: List <Sub>
        List<Sub> subList1 = new ArrayList<>();
        List<Super> superList = subList1;
        

        // 2、不支持逆变
        // 编译不通过:Required type: List <Sub>. Provided: ArrayList <Super>
        List<Sub> subList2 = new ArrayList<Super>();

        // 编译不通过:Required type: List <Sub>. Provided: List <Super>
        List<Super> superList2 = new ArrayList<>();
        List<Sub> subList = superList2;
    }


    public static void test2() {
    	// 1、实现协变
        // 创建一个泛型为 Super 的列表 list,其类型为 List<? extends Super>
        List<? extends Super> list = new ArrayList<Super>();

        // 创建一个子类为 Sub 的列表 subList 并向其中添加两个新的 Sub 对象
        List<Sub> subList = new ArrayList<>();
        subList.add(new Sub());
        subList.add(new Sub());
        // 将 subList 赋值给 list 变量,因为 subList 是一个子类列表,可以赋值给泛型为 Super 的列表
        list = subList;
        System.out.println(list);

        // 2、实现逆变
        // 创建一个泛型为 Sub 的超类列表 list2,其类型为 List<? super Sub>
        List<? super Sub> list2 = new ArrayList<Sub>();
        
        //  创建一个超类为 Super 的列表 superList 并向其中添加两个新的 Super 对象
        List<Super> superList = new ArrayList<>();
        superList.add(new Super());
        superList.add(new Super());
        //  将 superList 赋值给 list2 变量,因为 superList 是一个超类列表,可以赋值给泛型为 Sub 的列表
        list2 = superList;
        System.out.println(list2);
    }
}

在这个示例中,test1 展示了泛型类型的不变性。虽然 SuperSub 的父类,但是 List<Super> 并不是 List<Sub> 的父类,反之亦然。所以test1 里的代码全部无法通过编译,如下图:
在这里插入图片描述


test2 方法则展示了通过使用上限通配符(? extends T)来模拟实现协变,使用下限通配符(? super T)来模拟实现逆变。
运行结果:

[Sub{}, Sub{}]
[Super{}, Super{}]

7️⃣ 应用场景

泛型在实际开发中有很多应用场景,以下是一些常见的用法:

  • 容器类:泛型使得容器类(如列表、集合、映射)可以存储不同类型的数据,并提供类型安全的访问和操作;
  • 泛型算法:通过使用泛型方法,可以编写适用于多种类型的通用算法,减少了代码的重复,增加了代码的可重用性;
  • 数据结构:泛型也被广泛用于定义数据结构,如栈、队列、二叉树等。通过使用泛型,可以定义通用的数据结构,以便处理不同类型的数据;
  • 接口的泛型化:在设计接口时,可以使用泛型将其参数或返回类型与具体实现解耦,从而提高代码的灵活性和可扩展性;
  • 异常处理:Java 标准库中的异常类也使用了泛型,这样可以更好地捕获和处理特定类型的异常。

🌾 总结

泛型是 Java 语言提供的一种强大的功能,它允许在编译时对类型进行检查,并提高代码的类型安全性和可读性。通过在类、接口或方法的定义中使用类型参数,可以创建通用的数据结构和算法,并简化代码的开发过程。

尽管泛型的实现采用了类型擦除机制,导致在运行时无法获得泛型类型参数的具体类型信息,但是仍然可以通过通配符和反射等机制来操作泛型对象和获取相关的元数据。

在实际开发中,泛型被广泛应用于容器类、算法、数据结构、接口的设计以及异常处理等领域,它大大提高了代码的可重用性、可扩展性和可维护性。

掌握泛型的使用方法以及了解其原理和限制,将使开发人员能够更好地利用 Java 编程语言的强大功能,并编写更优雅、健壮且类型安全的代码。

📑 本文源码下载地址

Java语言 泛型讲解案例代码(泛型类、泛型接口、泛型方法、无界及上下限通配符、泛型对协变和逆变的支持、类型擦除 …)

在这里插入图片描述


在这里插入图片描述

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

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

相关文章

aardio - 【库】http访问网页

为了简化http访问操作&#xff0c;提高速度&#xff0c;丰富功能&#xff0c;特封装了此库&#xff0c;可以根据需要进行选择。 本库带一个dll&#xff0c;所以建议优先选择使用 inet.http 库&#xff1a; 如果使用 inet.http库&#xff0c;直接 inet.http.get() 速度较慢。 大…

理解3ds max中的容器的概念

实验一&#xff1a; 在场景中创建一个容器 把这个容器保存为一个文件&#xff0c;在文件夹中可看到此容器文件&#xff0c;其大小为892KB&#xff0c;同时可看到生成一个同名的lock类型文件。 将场景中的某一个物体&#xff08;面加多一点的&#xff09;添加到容器中&#x…

框架---面经

Spring 循环依赖 概念 多个实体之间相互依赖并形成闭环的情况就叫做"循环依赖”&#xff0c;也叫做”循环引用。 三级缓存解决循环依赖的原理 循环依赖的解决方案--- Feild注入单例&#xff08;AutoWired&#xff09; 直接在类的成员变量上使用Autowired注解&#xf…

SM2椭圆曲线公钥密码算法

国家密码管理局于2010年12月17日发布了SM2椭圆曲线公钥密码算法&#xff0c;并要求为对现有基于RSA算法的电子认证系统、密钥管理系统、应用系统进行升级改造。关于算法标准&#xff0c;请参见《国家密码管理局公告&#xff08;第 21 号&#xff09;》&#xff0c;网址为​​ht…

JavaWeb【总结】——(请求和响应)浏览器发送请求的方式 服务器响应的方式

本文目录 引出JavaWeb相关知识1.网页状态码web相关背景知识如何在idea中建tomcat web项目2.Web的请求request&#xff1a;get和post&#xff0c;响应response3.同步请求和异步请求Ajax&#xff0c;以及异步的Json响应4.同步jsp和异步ajax的axios下&#xff0c;转发或重定向思考…

【图片轮播】Vue如何实现移动端图片轮播效果,支持左右滑动(附图文及代码)

【写在前面】 日常生活中&#xff0c;其实我们是离不开手机查看相册的&#xff0c;尤其是图片的轮播展示&#xff0c;最近我就接到我家老大给出的需求&#xff0c;首先是从网上下载下来之前她做的图片&#xff0c;然后她就希望能够在自己手机上能随时查看&#xff0c;这不没办法…

Java使用OpenCV进行图像操作

OpenCV图像操作 OpenCV概述下载与安装目录说明项目集成验证 Mat类创建Mat对象其他操作 常见图像API读取与输出图像显示图像图像压缩和解压缩图像转换图像缩放亮度调整图像锐化图像梯度图像二值化边缘检测图像高斯模糊图像反色 OpenCV 概述 OpenCV&#xff08;开源计算机视觉库…

2023互联网高级测试工程师至少具备的能力

业务熟悉 熟悉本系统 测试人员参与测试的系统的各种业务场景&#xff0c;必须做到精熟 。一旦需求有改动&#xff0c;可以清楚快速的知道上下文。同时可以清楚的知道哪些点是需要重点测试的。 熟悉跟本系统有通讯的上下游系统业务 跟本系统有通讯的上下游系统也要非常熟悉。这…

Exception in thread “main“ java.lang.UnsupportedClassVersionError 50报错处理

之间正常走jenkinsdocker自动化部署的项目&#xff0c;今天改了一个文件&#xff0c;点了一下&#xff0c;竟然没有部署上去&#xff0c;提示如上&#xff0c;如下 Exception in thread "main" java.lang.UnsupportedClassVersionError: com/coocaa/tsp/sys/user/Use…

Web 自动化测试Selenium 之PO 模型

目录 1. po 模型介绍 2. PageObject 设计模式 3. PO 的核心要素 4. 非PO 实现 5. PO 实现 6. 总结 7. PO 模式的特点 总结&#xff1a; 1. po 模型介绍 在自动化中&#xff0c;Selenium 自动化测试中有一个名字经常被提及 PageObject (思想与面向对象的特征相同)&#x…

【改进算法】混合鲸鱼WOA和BAT算法(Matlab代码实现)​

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Python键盘监听:实现快捷操作和自动化脚本(监听组合键

前言 本文主要介绍一下使用Python进行事件监听功能&#xff0c;以实现一些特有的操作。本文旨在介绍如何实现这一功能。 笔者根据一些需求写了一个小工具&#xff0c;流程和功能如下图所示&#xff08;实际功能有更多&#xff09;&#xff1a; 该工具主要实现了 键盘监听 和 鼠…

从Linux源码看TIME_WAIT状态的持续时间

前言 笔者一直以为在Linux下TIME_WAIT状态的Socket持续状态是60s左右。线上实际却存在TIME_WAIT超过100s的Socket。由于这牵涉到最近出现的一个复杂Bug的分析。所以&#xff0c;笔者就去Linux源码里面&#xff0c;一探究竟。 首先介绍下Linux环境 TIME_WAIT这个参数通常和五…

C++入门,一些C++基本概念介绍

文章目录 目录 前言 1.C关键字 1.1命名空间 1.2命名空间定义 1.3命名空间的使用 2.C输入&输出 3.缺省参数 3.1缺省参数的概念 3.2缺省参数分类 4.函数重载 4.1函数重载的概念 5.引用 5.1 引用特性 5.2 常引用 5.3引用的使用场景 5.4引用和指针 6.内联函数…

【Java基础】注解——自定义注解

什么是注解? Java 注解(Annotation)又称 Java 标注&#xff0c;是 JDK5.0 引入的一种注释机制。 比如我们常见的Override和Deprecated都是注解&#xff0c;注解可以加在类、方法、成员变量等上面&#xff0c;类似于给他们“打标签"。 注解怎么定义? public interface…

华为OD机试真题 JavaScript 实现【百钱买百鸡问题】【牛客练习题】

一、题目描述 公元五世纪&#xff0c;我国古代数学家张丘建在《算经》一书中提出了“百鸡问题”&#xff1a;鸡翁一值钱五&#xff0c;鸡母一值钱三&#xff0c;鸡雏三值钱一。百钱买百鸡&#xff0c;问鸡翁、鸡母、鸡雏各几何&#xff1f; 现要求你打印出所有花一百元买一百…

AM@空间直角坐标系@数量积和向量积@向量的外积在物理学中的相关概念

文章目录 空间直角坐标系坐标面分向量坐标分解式余弦定理数量积的坐标表示公式 向量积向量积的坐标表示公式 向量的外积在物理学中的相关概念物理量ref 角速度和向量积量纲Base unit (measurement)Background&#x1f388;International System of Units&#x1f388;附 表达方…

【ROS】ROS1导航(了解)

1、简述 ROS1导航模块navigation&#xff0c;它从里程计、传感器流和目标姿势中获取信息&#xff0c;并将速度、角速度控制命令发送至差速控制单元。 因为是ROS1&#xff0c;所以下面的内容只是一带而过&#xff0c;没有深入学习总结。详细内容可参考官网&#xff1a;http://…

Spring高手之路5——彻底掌握Bean的生命周期

文章目录 1. 理解Bean的生命周期1.1 生命周期的各个阶段 2. 理解init-method和destroy-method2.1 从XML配置创建Bean看生命周期2.2 从配置类注解配置创建Bean看生命周期2.3 初始化和销毁方法的特性2.4 探究Bean的初始化流程顺序 3. PostConstruct和PreDestroy3.1 示例&#xff…

Scala入门

第1章 Scala入门 1.1 概述 Scala将面向对象和函数式编程结合成一种简洁的高级语言。 语言特点如下&#xff1a; &#xff08;1&#xff09;Scala和Java一样属于JVM语言&#xff0c;使用时都需要先编译为class字节码文件&#xff0c;并且Scala能够直接调用Java的类库。 &#…