Java中的泛型

一. 泛型简介
泛型,即“参数化类型”。
作为Java中常用且重要的一个概念,泛型帮我们实现了代码重用,也保证了类型安全。但关于它的详细内容,目前很多同学还不清楚,所以接下来就带各位来学习这个重要的知识点。

  1. 背景

为了能够让大家更好地理解泛型的作用,在我们开始学习泛型之前,先给大家提个开发需求:

我们现在有一个需求,要求你编写一个对数组进行排序的方法,该方法能够对浮点型数组、整型数组、字符串数组或者是其他任何类型的数组进行排序,你该如何实现?

有的小伙伴会说,这很简单啊,我可以利用方法重载,针对每种类型的数组分别编写一个排序方法,需要为几种类型的数组排序,我就定义几个排序方法。如果你是这么实现的,只能哈哈哈了,这种做法明显不好,代码可重用性太差。

又有的小伙伴说了,可以定义一个方法,里面设置一个Object[]类型的参数,这样无论是哪种类型都可以处理了。这样定义方法,比上面那个同学的想法要稍好一点,但此时我们需要在Object类型和整型、String类型或其他类型之间进行强制类型转换。所以这样做就无法保证集合中元素的类型安全,稍一不慎就可能会导致 ClassCastException类型转换异常。

so,这也不行,那也不行,到底该怎么办?这不,为了解决这些问题,所以Java中就产生了泛型这个技术。

  1. 概念

泛型(generics) 这个技术是在JDK 5中引入的新特性,它的本质其实是类型参数化, 利用泛型可以实现一套代码对多种数据类型的动态处理,保证了更好的代码重用性。并且泛型还提供了编译时对类型安全进行检测的机制,该机制允许我们在编译时就能够检测出非法的类型, 提高了代码的安全性。

这种特性,使得泛型成了一种 “代码模板” ,让我们利用一套代码就能实现对各种类型的套用。也就是说,我们只需要编写一次代码,就可以实现万能匹配,这也是”泛型“这个概念的含义,你可以将其理解为”广泛的类型“、”非特定的类型“。咱们上面的那个需求,利用泛型就能轻松实现,还不需要进行类型的强制转换,并且也保证了数据的类型安全。

  1. 作用

所以根据上面泛型的概念,我们可以提取出泛型的核心作用:

泛型可以在编译时对类型进行安全检测,使得所有的强制转换都是自动隐式实现的,保证了类型的安全性;

泛型作为”代码模板“,实现了 一套代码对各种类型的套用, 提高了代码的可重用性。

  1. 使用场景

基于泛型的这些特性和作用,我们可以把泛型用在很多地方,在这里给大家做了一个总结,通常情况下,泛型可以用在如下场景中:

1.泛型集合:在各种集合中使用泛型,保证集合中元素的类型安全;2.泛型方法:在各种方法中使用泛型,保证方法中参数的类型安全;3.泛型类:在类的定义时使用泛型,为某些变量和方法定义通用的类型;4.泛型接口:在接口定义时使用泛型,为某些常量和方法定义通用的类型;5.泛型加反射:泛型也可以结合反射技术,实现在运行时获取传入的实际参数等功能。

但是我们要注意,无论我们在哪个地方使用泛型,泛型都不能是基本类型, 关于这一点,我会在讲解泛型擦除时再细说。

总之,泛型的应用场景有很多,以上只是给大家总结的几个重点使用场景,接下来就这几个场景分别给大家进行讲解。

二. 泛型集合

  1. 简介

泛型最常见的一个用途,就是在集合中对数据元素的类型进行限定。集合作为一个容器,主要是用来容纳保存数据元素的,但集合的设计者并不知道我们会用集合来保存什么类型的对象,所以他们就把集合设计成能保存任何类型的对象。这就要求集合具有很好的通用性,内部可以装载各种类型的数据元素。集合之所以可以实现这一功能,主要是集合的源码中已经结合泛型做了相关的设计,我们来看看Collection的源码,如下图所示:
在这里插入图片描述
而Collection的子类List中也增加了对泛型的支持,如下图所示:
在这里插入图片描述
上面的源码中,集合中的< E >就是泛型,至于泛型的名字为什么叫做”E“,后面再跟大家细说。但不管如何,从这些源码中我们就可以看出,Java的集合本身就支持泛型了。我们先不管集合底层是如何设计的,咱们先从基本用法开始学起。

  1. 语法

在集合中使用泛型其实比较简单,我们以List集合为例,其基本语法如下:
在这里插入图片描述
上面的语法,其含义是说我们定义了一个ArrayList集合,但该集合不能随便添加数据元素,只能添加String类型的元素。也就是说,在上面的语法中,我们通过泛型,限定了ArrayList集合的元素类型。当我们定义List集合时,如果已经限定了泛型类型,但后面添加元素时你非得违背这个类型,Java就会在编译阶段报错,如下图所示:
在这里插入图片描述
我们在定义集合时,可以省略后面ArrayList里的String,编译器可以自动根据前面< >里的类型,推断出后面< >里使用的泛型类型。另外Set和Map集合的用法,与List集合类似,我们可以通过下面这个案例来体会一下集合泛型的魅力。

  1. 代码案例

在本案例中,我们可以给List、Set、Map等集合设置泛型,从而限定集合中数据元素的类型。
在这里插入图片描述
在这个案例中,我们在集合中通过泛型限定了集合元素的数据类型。如果元素的类型与要求的不一致,在编译阶段就会检测出有错误,不需要进入到运行阶段才能发现类型不一致。而且我们 在获取集合中的元素时,也不需要进行强制类型转换,程序会自动进行隐式转换, 这就保证了数据的安全性,也提高了代码的执行效率。

另外我们所使用的泛型参数,也被称为类型变量,是用于指定泛型类型名称的标识符。我们可以根据需要,在集合、类、接口、方法等地方定义一个或多个泛型参数,这些泛型化的类型参数也被称为参数化的类或参数化的类型。

三. 泛型接口
我们除了可以在集合中使用泛型,还可以在定义接口时使用泛型,这也是泛型的常用形式之一。

  1. 语法

在定义接口时使用泛型的基本语法格式如下:
在这里插入图片描述
大家注意,这里泛型的名称T/M/N,其实是我们随意写的,我们并不一定非要使用T,也可以使用M、N、E等任意名称。而之所以使用T,只是采用了Type类型这个单词的首字母而已。虽然如此,但我们在实际开发时,为了尽量做到见名知意,请大家还是要尽量采用有意义的名称,通常会使用如下几个常用字母:

E - Element(表示集合元素,常在集合中使用);T - Type(表示Java类,常用在类和接口中);K - Key(表示键);V - Value(表示值);N - Number(表示数值类型);? - 表示不确定的Java类型。

另外,这里的T只是一种类型参数,你可以把它理解成是一个”表面的占位符“。在真正赋值时,它可以用任何实际的类型来替代,如Integer、String、自定义类型等。并且我们在定义接口时,可以根据实际需要,同时定义多个泛型,多个泛型之间用","逗号分割。而在实际使用时,我们需要在该接口名的后面加上一对尖括号,用来传入实际的类型。

  1. 代码案例
    2.1 定义泛型接口

接下来我们再通过一个案例来学习一下接口泛型如何使用,这里我们定义一个泛型接口ICompute,内部定义了一个用于计算的方法,如下所示:
在这里插入图片描述
2.2 实现泛型接口

接下来我们把这个接口进行实现,代码如下:
在这里插入图片描述
这里直接利用匿名内部类的写法进行实现,大家也可以编写一个类实现ICompute接口。我这里传入了两个Integer类型的具体参数,分别取代M和N,当然我们也可以根据需要,在实现时传入Float/Double等其他类型。

四. 泛型类
其实Java的类和接口在很多地方都很类似,所以我们在定义接口时可以使用泛型,也可以在定义类时使用泛型,泛型类常用于类中的属性类型不确定的情况下,这也是泛型的常用形式之一。

  1. 语法

其实泛型类的声明和普通类的声明类似,只是在类名后面多添加了一个关于泛型的声明。并且泛型类的类型参数部分,可以包含一个或多个类型参数,多个参数间用逗号隔开。一般我们在定义泛型类时,需要在类名后添加类型参数,语法格式与泛型接口一致,如下所示:
在这里插入图片描述
泛型类的要求和泛型接口完全一样,这里就不再赘述了。

  1. 代码案例
    2.1 定义泛型类

接下来定义一个泛型类Pair,它包含两个类型相同的成员变量:
在这里插入图片描述
在上述代码中,我们定义了一个泛型类Pair,它有两个类型相同的成员变量first和second,以及一个构造函数和两个访问成员变量的方法。在定义Pair类时,我们使用了类型参数T来代表类型,而在实例化该泛型类时,需要指明泛型类中的类型参数,并赋予泛型类属性相应类型的值,比如指定T是
String/Integer/Student/Person等任意类型。

2.2 使用泛型类

接下来是使用Pair类的具体代码:
在这里插入图片描述
在上述代码中,我们使用了Pair类,并将类型参数指定为String类型。然后我们创建了一个Pair对象,并通过getFirst和getSecond方法访问了成员变量。

五. 继承泛型类和实现泛型接口
在Java中,泛型不仅可以用于类、方法的定义,还可以用于类和接口的继承与实现。接下来就给大家详细介绍一下,该如何继承泛型类和实现泛型接口。

  1. 简介

大家要注意,一个被定义为泛型的类和接口,也可以被子类继承和实现。例如下面的示例代码,就给大家演示了如何继承一个泛型类。
在这里插入图片描述
但是如果我们想要SonClass类在继承FatherClass类时,能够保留父类的泛型类型,则需要在继承时就指定。否则直接使用extends FatherClass语句进行继承操作时,T1、T2 和 T3都会自动变为Object类型,所以一般情况下都是将父类的泛型类型保留。

接下来会分别给大家介绍一下如何继承泛型类和实现泛型接口。

  1. 继承泛型类
    2.1 定义泛型父类

在Java中,我们可以通过继承一个泛型类来实现泛型的重用。子类可以继承父类中定义的泛型类型,并根据自己的需要,增加、修改泛型类型的参数,从而实现泛型类的个性化定制。下面是一个泛型类的示例:
在这里插入图片描述
2.2 泛型子类继承父类

我们可以通过继承GenericClass类,来创建一个新的泛型类SonGenericClass,并增加新的泛型类型:
在这里插入图片描述
在上面的示例中,SonGenericClass类继承了GenericClass类,并增加了一个新的泛型类型T2。在构造方法中,调用父类的构造方法,并传入T1类型的数据,然后再将T2类型的数据赋值给类的成员变量otherData。通过这种方式,我们可以创建一个具有更多泛型参数的类,并且保留了原始泛型类的特性。我们来看看最终的测试结果:
在这里插入图片描述
这样,子类通过继承父类,也自动获得了父类中的泛型。

6、泛型方法

在java中,泛型类的定义非常简单,但是泛型方法就比较复杂了。尤其是我们见到的大多数泛型类中的成员方法也都使用了泛型,有的甚至泛型类中也包含着泛型方法,这样在初学者中非常容易将泛型方法理解错了。

泛型类:是在实例化类的时候指明泛型的具体类型;
泛型方法:是在调用方法的时候指明泛型的具体类型 。

/*** 泛型方法的基本介绍* @param tClass 传入的泛型实参* @return T 返回值为T类型* 说明:*     1)public 与 返回值中间<T>非常重要,可以理解为声明此方法为泛型方法。*     2)只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。*     3)<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。*     4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。*/
public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,IllegalAccessException{T instance = tClass.newInstance();return instance;
}

调用,返回

Object obj = genericMethod(Class.forName("com.test.test"));

静态方法有一种情况需要注意一下,那就是在类中的静态方法使用泛型:静态方法无法访问类上定义的泛型;如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上。

即:如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法 。

  1. Java 泛型擦除
Java 泛型的参数只可以代表类,不能代表个别对象。
由于 Java 泛型的类型参数之实际类型在编译时会被消除,所以无法在运行时得知其类型参数的类型。Java 编译器在编译泛型时会自动加入类型转换的编码,故运行速度不会因为使用泛型而加快。

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。

Java中泛型其实是伪泛型;
例如:在编译阶段,泛型类Box会被实例化为Box和Box。编译器会根据需要插入类型转换代码来保证类型安全。
然而,在运行时,所有的泛型类型参数T都会被擦除,stringBox和integerBox实际上是相同的类型Box。因此,存放在盒子中的数据在运行时都被当作Object类型处理。
最后会多做一步强转,通过类型转换为泛型类型,这样可以确保获取到正确的数据类型。

JVM并不知道泛型的存在,因为泛型在编译阶段就已经被处理成普通的类和方法;
处理机制是通过类型擦除,擦除规则:

1.若泛型类型没有指定具体类型,用Object作为原始类型;
2.若有限定类型< T exnteds XClass >,使用XClass作为原始类型;
3.若有多个限定< T exnteds XClass1 & XClass2 >,使用第一个边界类型XClass1作为原始类型;

示例:

在Springboot中,调用RESTful api时常用的方法主要有两种:

通过自带的RestTemplate 或者 自己写http客户端访问工具来实现服务调用

基本上RestTemplate已经可以满足需要了

RestTemplate其实是对http请求中一些模块化代码的封装,比如建立连接、构造请求头 请求体、解析响应信息、关闭连接等,是Springboot对HttpClient的封装,简化了http请求过程,减少冗余代码。

主要方法:
RestTemplate封装了常用http请求,比如GET、POST、PUT、DELETE等,可以方便的调用,主要请求方法如下:

public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientExceptionpublic <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientExceptionpublic <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientExceptionpublic <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientExceptionpublic void put(String url, @Nullable Object request, Object... uriVariables) throws RestClientExceptionpublic void delete(String url, Object... uriVariables) throws RestClientExceptionpublic <T> ResponseEntity<T> exchange(String url, HttpMethod method, @Nullable HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) throws RestClientExceptionpublic <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException

这些方法使用起来是比较简单的,其中xxForObject返回的是接口返回值,xxForEntity返回的除了接口返回值 还包括http返回信息。

对于exchange和execute使用起来就比较灵活了,里面有个参数 HttpMethod,可以使用各种请求方式进行请求,比如用HttpMethod.GET方法进行GET请求。

HttpMethod是一个枚举:
在这里插入图片描述

RestTemplate exchange方法使用:
1、先新建一个springboot工程,端口取默认 8080,然后新建一个Controller,如下:

@RestController
public class RemoteRestController {@GetMapping("rest")public String usedForRemoteRest(){return "Hi there, from remote";}
}

如果调用成功,会返回一个字符串

2、再新建一个springboot工程,端口取8081,工程名比如取ex,方便辨认

server.port=8081

3、在新建的ex工程中,新建一个Controller,准备调用RestTemplate方法,去访问第一个工程中的接口:

@RestController
public class RestTestController {private static final String REMOTE_URL = "http://localhost:8080/";@GetMapping("rtest")public String restGetValue(HttpServletRequest req){RestTemplate restTemplate = new RestTemplate();String ret = restTemplate.getForObject(REMOTE_URL + "rest", String.class);System.out.println("====================ret: " + ret);ResponseEntity<String> retEntity = restTemplate.getForEntity(REMOTE_URL + "ret", String.class);return "";}
}

分别运行两个spring工程,在浏览器中输入http://localhost:8081/rtest ,可以看到返回:
在这里插入图片描述
在ex工程中下断点,可以看到getForObject和getForEntity返回值的区别:
在这里插入图片描述
在这里插入图片描述
可以看到getForEntity返回信息会包括http的信息。

上面是简单的使用
在源码中我们可以看到,xxForObject, xxForEntity都是有返回值,而对于put, delete访问需要得到返回值,使用:

public void put(String url, @Nullable Object request, Object... uriVariables) throws RestClientExceptionpublic void delete(String url, Object... uriVariables) throws RestClientException

这两个方法就无能为力了

这时我们可以使用exchange方法来使用,具体如下:

在测试springboot工程中,写一个put方法的controller:

@PutMapping("restput")public String putMethod(){return "PUT method invoke";}

可以封装一个exchange方法:

private <T, A> T exchange1(String url, HttpMethod method, Class<T> responseBodyType, A requestBody) {RestTemplate template = new RestTemplate();// 请求头HttpHeaders headers = new HttpHeaders();MimeType mimeType = MimeTypeUtils.parseMimeType("application/json");MediaType mediaType = new MediaType(mimeType.getType(), mimeType.getSubtype(), Charset.forName("UTF-8"));// 请求体headers.setContentType(mediaType);// 发送请求HttpEntity<A> entity = new HttpEntity<>(requestBody, headers);ResponseEntity<T> resultEntity = template.exchange(url, method, entity, responseBodyType);return resultEntity.getBody();}

responseBody: 代表返回值类型

requestBody: 代表请求体中的body参数

在ex工程中写一个测试请求接口:

@GetMapping("rput")public String restPUTValue(HttpServletRequest req){String ret = exchange(REMOTE_URL + "restput", HttpMethod.PUT, String.class, null);return "RETURN: " + ret;}

在浏览器中输入:

http://localhost:8081/rput

会发现返回结果显示出来了:
在这里插入图片描述
exchange方法返回值中有泛型类型情况:
前面介绍的exchange方法是处理RestTemplate自带的put, delete方法中没有返回值的情况,但是包括get, post等方法,如果返回值中有泛型值,RestTemplate自带的getForEntity, getForObject等其实也是处理不了的,这时也可以使用exchange来代替,具体如下:

可以对上面封装的exchange方法进行改造,传入一个ParameterTypeReference对象:

public static <T, A> T exchange2(String url, HttpMethod method, ParameterizedTypeReference<T> responseBodyType, A requestBody) {RestTemplate restTemplate = new RestTemplate();// 请求头HttpHeaders headers = new HttpHeaders();MimeType mimeType = MimeTypeUtils.parseMimeType("application/json");MediaType mediaType = new MediaType(mimeType.getType(), mimeType.getSubtype(), Charset.forName("UTF-8"));// 请求体headers.setContentType(mediaType);// 发送请求HttpEntity<A> entity = new HttpEntity<>(requestBody, headers);ResponseEntity<T> resultEntity = restTemplate.exchange(url, method, entity, responseBodyType);return resultEntity.getBody();}

测试代码:

两个springboot工程分别,服务提供方、服务消费方:

场景1:泛型 返回字符串

服务提供方代码:
@PostMapping("/rpctop")public String rpctop(@RequestBody UserVO userVO){return "张贵";}服务消费方代码:
public String getUserName() throws JsonProcessingException {HttpHeaders headers = new HttpHeaders();headers.add("x-auth-token","123");headers.setContentType(MediaType.APPLICATION_JSON);ObjectMapper objectMapper = new ObjectMapper();Map<String, Object> map = new HashMap<>();map.put("name", "1111");map.put("age", "19");HttpEntity requestEntity = new HttpEntity(map, headers);//调用方式1Integer response = restTemplate.exchange("http://127.0.0.1:8080/ccbServer/tx/rpctop", HttpMethod.POST, String.class, map);//调用方式2//ParameterizedTypeReference<String> responseBodyType = new ParameterizedTypeReference<String>() {};//Person response = restTemplate.exchange("http://127.0.0.1:8080/ccbServer/tx/rpctop", HttpMethod.POST, responseBodyType, map);return response;}

场景2:泛型 返回Integer数据

服务提供方代码:
@PostMapping("/rpctop")public Integer rpctop(@RequestBody UserVO userVO){return 666;}服务消费方代码:
public Integer getUserName() throws JsonProcessingException {HttpHeaders headers = new HttpHeaders();headers.add("x-auth-token","123");headers.setContentType(MediaType.APPLICATION_JSON);ObjectMapper objectMapper = new ObjectMapper();Map<String, Object> map = new HashMap<>();map.put("name", "1111");map.put("age", "19");HttpEntity requestEntity = new HttpEntity(map, headers);//调用方式1Integer response = restTemplate.exchange("http://127.0.0.1:8080/ccbServer/tx/rpctop", HttpMethod.POST, Integer.class, map);       //调用方式2//ParameterizedTypeReference<Integer> responseBodyType = new ParameterizedTypeReference<Integer>() {};//Person response = restTemplate.exchange("http://127.0.0.1:8080/ccbServer/tx/rpctop", HttpMethod.POST, responseBodyType, map);return response;}

场景3:泛型 返回Person实体

服务提供方代码:
@PostMapping("/rpctop")public Person rpctop(@RequestBody UserVO userVO){Person person = new Person();person.setName("zjg");person.setAge(10);return person;}服务消费方代码:
public Integer getUserName() throws JsonProcessingException {HttpHeaders headers = new HttpHeaders();headers.add("x-auth-token","123");headers.setContentType(MediaType.APPLICATION_JSON);ObjectMapper objectMapper = new ObjectMapper();Map<String, Object> map = new HashMap<>();map.put("name", "1111");map.put("age", "19");HttpEntity requestEntity = new HttpEntity(map, headers);//调用方式1Person response = restTemplate.exchange("http://127.0.0.1:8080/ccbServer/tx/rpctop", HttpMethod.POST, Person.class, map);//调用方式2//ParameterizedTypeReference<Person> responseBodyType = new ParameterizedTypeReference<Person>() {};//Person response = restTemplate.exchange("http://127.0.0.1:8080/ccbServer/tx/rpctop", HttpMethod.POST, responseBodyType, map);return response.getName();}

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

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

相关文章

利用fiddler正向代理前端请求到本地后端

前景&#xff1a;在实际开发测试环境中&#xff0c;&#xff08;前后端均已上线到测试服务器或前端以上线而后端还在开发中)。在测试过程中&#xff08;前端页面点击&#xff0c;功能测试&#xff09;发现了bug或异常点。 正常排查问题可能是先利用浏览器检查工具查看接口的返回…

flv怎么转换成mp4格式?准备3个方法给大家

flv怎么转换成mp4格式&#xff1f;FLV是一种流行的视频文件格式&#xff0c;最初由Adobe公司开发&#xff0c;用于在Web上播放和传输视频内容。FLV格式以其较小的文件大小和较高的压缩比而闻名&#xff0c;并广泛应用于在线视频分享平台、流媒体服务和网络广告等领域。能够提供…

驱动开发---基于gpio子系统编写LED灯的驱动

一、GPIO子系统相关API 1.解析GPIO相关的设备树节点 struct device_node *of_find_node_by_path(const char *path) 功能&#xff1a;根据设备树节点路径解析设备树节点信息 参数&#xff1a; path&#xff1a;设备树所在的节点路径 /mynode0X12345678 返回值&#xff1a;成…

JS的基本组成

JavaScript的实现包括以下3个部分&#xff1a; 模块功能ECMAScript(核心)描述了JS的语法和基本对象。文档对象模型 &#xff08;DOM&#xff09;处理网页内容的方法和接口浏览器对象模型&#xff08;BOM&#xff09;与浏览器交互的方法和接口 javascript 有三部分构成&#…

腾讯mini项目-【指标监控服务重构-会议记录】2023-07-26

2023-07-26组长会议纪要 A组 项目对齐和问题 分配需求&#xff0c;SLI指标上报&#xff0c;暂时没有实际效果 每个人负责一条指标&#xff0c;同步代码&#xff0c;时间问题还是难题跟B组同学请教&#xff0c;答疑 问题&#xff1a;启动 Tracer 【已解决】 环境问题&#xf…

Python读取Excel每一行为列表—大PK(openpyxl\pandas\xlwings\xlrd)看谁用时少?

目录 背景使用—openpyxl&#xff08;耗时89秒输出&#xff09;使用—pandas&#xff08;耗时44秒输出&#xff09;使用—xlwings&#xff08;耗时15秒输出&#xff09;使用—xlrd&#xff08;耗时47秒输出&#xff09;总结 背景 我们在平常办公的时候&#xff0c;尤其是财务人…

asisctf 2023 web hello wp

hello 开题&#xff0c;直接给了源码。 <?php /* Read /next.txt Hint for beginners: read curls manpage. */ highlight_file(__FILE__); $url file:///hi.txt; if(array_key_exists(x, $_GET) &&!str_contains(strtolower($_GET[x]),file) && !str_c…

ElementUI之动态树+数据表格+分页

目录 前言 一.ElementUI之动态树 1.前端模板演示 2.数据绑定 2.1 通过链接获取后台数据 2.2 对链接进行绑定 2.3添加动态路由 2.4 配置路由 3.效果演示 二.数据表格动态分页 1.前端模板 2.通过JS交互获取后端数据 3 效果演示 前言 Element UI 是一个基于 Vue.js 的开…

64位Ubuntu20.04.5 LTS系统安装32位运行库

背景&#xff1a; 在ubutu&#xff08;版本为20.04.5 LTS&#xff09;中运行./arm-none-linux-gnueabi-gcc -v 后提示“no such device”。 经多方查证&#xff0c;是ubutu的版本是64位的&#xff0c;而需要运行的编译工具链是32位的&#xff0c;因此会不兼容。 解决方法就是在…

反射学习笔记

反射学习笔记 一、反射入门案例 在反射中&#xff0c;万物皆对象&#xff0c;方法也是对象。反射可以在不修改源码的情况下&#xff0c;只需修改配置文件&#xff0c;就能实现功能的改变。 实体类 /*** 动物猫类*/ public class Cat {private String name;public void hi()…

系统安全测试要怎么做?

进行系统安全测试时&#xff0c;可以按照以下详细的步骤进行&#xff1a; 1、信息收集和分析&#xff1a; 收集系统的相关信息&#xff0c;包括架构、部署环境、使用的框架和技术等。 分析系统的安全需求、威胁模型和安全策略等文档。 2、威胁建模和风险评估&#xff1a; …

gitee-快速设置

快速设置— 如果你知道该怎么操作&#xff0c;直接使用下面的地址 HTTPS SSH: gitgitee.com:liuzl33078235/esp-idf.git 我们强烈建议所有的git仓库都有一个README, LICENSE, .gitignore文件 初始化 readme 文件 Git入门&#xff1f;查看 帮助 , Visual Studio / TortoiseG…

el-table 指定层级展开

先来看看页面默认全部展开时页面的显示效果&#xff1a;所有节点被展开&#xff0c;一眼望去杂乱无章&#xff01; 那么如何实现只展开指定的节点呢&#xff1f;最终效果如下&#xff1a;一眼看去很舒爽。 干货上代码&#xff1a; <el-table border v-if"refreshTabl…

软件测试-测试用例

软件测试-测试用例 1.什么是测试用例 为了实施测试而向被测系统提供的一组集合。这组集合包括测试环境、操作步骤、测试数据、预期结果等要素。 举例&#xff1a;对一个垃圾桶设计测试用例 2.设计测试用例的万能公式 设计测试用例的万能公式&#xff1a;功能测试性能测试界…

卤制品配送经营商城小程序的用处是什么

卤制品也是食品领域重要的分支&#xff0c;尤其对年轻人来说&#xff0c;只要干净卫生好吃价格合理&#xff0c;那复购率宣传性自是不用说&#xff0c;而随着互联网发展&#xff0c;传统线下门店也须要通过线上破解难题或进一步扩大生意。 而商城小程序无疑是商家通过线上私域…

【漏洞复现】企望制造 ERP命令执行

漏洞描述 由于企望制造 ERP comboxstore.action接口权限设置不当&#xff0c;默认的配置可执行任意SQL语句&#xff0c;利用xp_cmdshell函数可远程执行命令&#xff0c;未经认证的攻击者可通过该漏洞获取服务器权限。 免责声明 技术文章仅供参考&#xff0c;任何个人和组织…

Maven项目package为jar包后在window运行报A JNI error has occurred

原因&#xff1a;本地java版本与项目结构中使用的java版本不一致&#xff08;之前因为别的需求把idea的java版本改为了18&#xff09; 解决方法 打开项目结构&#xff0c;将idea的java版本改为与本地一致 再修改项目中的pom.xml 重新编译&#xff0c;package即可

Spark集成ClickHouse(笔记)

目录 前言&#xff1a; 一.配置环境 1.安装clickhouse驱动 2.配置clickhouse环境 二.spark 集成clickhouse 直接上代码&#xff0c;里面有一些注释哦&#xff01; 前言&#xff1a; 在大数据处理和分析领域&#xff0c;Spark 是一个非常强大且广泛使用的开源分布式计算框架…

uni-app:实现页面效果1

效果 代码 <template><view><view class"add"><image :src"add_icon" mode""></image></view><view class"container_position"><view class"container_info"><view c…

【SQL server】数据库入门基本操作教学

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️初识JAVA】 前言 数据库是计算机系统中用于存储和管理数据的一种软件系统。它通常由一个或多个数据集合、管理系统和应用程序组成&#xff0c;被广泛应用于企业、政府和个人等各种领域。目前常用的数…