Java 기본 튜토리얼칼럼에서는 오늘 Kotlin의 공분산과 반공분산을 소개합니다.
서문
Kotlin과 Java의 공분산과 반공분산을 더 잘 이해하기 위해 먼저 몇 가지 기본 지식을 살펴보겠습니다.
일반 할당
Java에서 공통 할당문은 다음과 같습니다.
A a = b;复制代码
대입문이 충족해야 하는 조건은 다음과 같습니다. 왼쪽이 오른쪽의 상위 클래스이거나 오른쪽과 동일한 유형입니다. 옆. 즉, A 유형은 Object o = new String("s");
와 같이 B 유형보다 "더 커야" 합니다. 이하에서는 편의상 A> Object o = new String("s");
。为了方便起见,下文中称作 A > B。
除了上述最常见的赋值语句,还有两种其他的赋值语句:
函数参数的赋值
public void fun(A a) {}// 调用处赋值B b = new B(); fun(b);复制代码
在调用 fun(b) 方法时,会将传入的 B b 实参赋值给形参 A a,即 A a = b
的形式。同样的,必须要满足形参类型大于实参,即 A > B。
函数返回值的赋值
public A fun() { B b = new B(); return b; } 复制代码
函数返回值类型接收实际返回类型的值,实际返回类型 B b 相当于赋值给了函数返回值类型 A a,即 B b 赋值给了 A a, 即 A a = b
,那么必须满足 A > B 的类型关系。
所以,无论哪种赋值,都必须满足左边类型 > 右边类型,即 A > B。
Java 中的协变与逆变
有了前面的基础知识,就可以方便地解释协变与逆变了。
如果类 A > 类 B,经过一个变化 trans 后得到的 trans(A) 与 trans(B) 依旧满足 trans(A) > trans(B),那么称为协变。
逆变则刚好相反,如果类 A > 类 B,经过一个变化 trans 后得到的 trans(A) 与 trans(B) 满足 trans(B) > trans(A),称为逆变。
比如大家都知道 Java 的数组是协变的,假如 A > B,那么有 A[] > B[],所以 B[] 可以赋值给 A[]。举个例子:
Integer[] nums = new Integer[]{}; Object[] o = nums; // 可以赋值,因为数组的协变特性所以由 Object > Integer 得到 Object[] > Integer[]复制代码
但是 Java 的泛型则不满足协变,如下:
List<Integer> l = new ArrayList<>(); List<Object> o = l;// 这里会报错,不能编译复制代码
上述代码报错,就是因为,虽然 Object > Integer,但是由于泛型不满足协变,所以 List<object></object>
> List<integer></integer>
是不满足的,既然不满足左边大于右边这个条件,从前言中我们知道,自然就不能将 List
Java 中泛型如何实现协变与逆变
从前面我们知道,在 Java 中泛型是不支持型变的,但是这会产生一个让人很奇怪的疑惑,也是很多讲泛型的文章中提到的:
如果 B 是 A 的子类,那么 List 就应该是 List 的子类呀!这是一个非常自然而然的想法!
但是很抱歉,由于种种原因,Java 并不支持。但是,Java 并不是完全抹杀了泛型的型变特性,Java 提供了 extends T> 和 super T> 使泛型拥有协变和逆变的特性。
extends T> 与 super T>
extends T> 称为上界通配符, super T> 称为下界通配符。使用上界通配符可以使泛型协变,而使用下界通配符可以使泛型逆变。
比如之前举的例子
List<Integer> l = new ArrayList<>(); List<Object> o = l;// 这里会报错,不能编译复制代码
如果使用上界通配符,
List<Integer> l = new ArrayList<>(); List<? extends Object> o = l;// 可以通过编译复制代码
这样,List extends Object> 的类型就大于 List
同样,下界通配符 super T> 可以实现逆变,如:
public List<? super Integer> fun(){ List<Object> l = new ArrayList<>(); return l; }复制代码
上述代码怎么就实现逆变了呢?首先,Object > Integer;另外,从前言我们知道,函数返回值类型必须大于实际返回值类型,在这里就是 List super Integer>
> List<object></object>
함수 매개 변수 할당public class Container<T> { private T item; public void set(T t) {
item = t;
} public T get() { return item;
}
}复制代码
🎜fun(b) 메서드를 호출할 때, 전달된 실제 매개변수 B b 는 형식 매개변수 A a 에, 즉 A a = b
형식으로 할당됩니다. 마찬가지로 형식 매개변수 유형은 실제 매개변수보다 커야 합니다. 즉, A > B입니다. 🎜함수 반환값 지정🎜Container<Object> c = new Container<String>(); // (1)编译报错Container<? extends Object> c = new Container<String>(); // (2)编译通过c.set("sss"); // (3)编译报错Object o = c.get();// (4)编译通过复制代码
🎜함수 반환값 형식은 실제 반환값 형식의 값을 받습니다. B b 실제 반환값 형식은 함수 반환값 형식을 지정하는 것과 동일합니다. A a, 즉 B b 가 A a, 즉 A a = b
에 할당되면 A > B의 유형 관계가 충족되어야 합니다. 🎜🎜그러므로 어떤 종류의 과제라도 left type > right type, 즉 A > B를 만족해야 합니다. 🎜Java의 공분산과 반공변성🎜🎜이전의 기본 지식으로 공분산과 반공변성을 쉽게 설명할 수 있습니다. 🎜🎜클래스 A > 클래스 B, trans 변경 후에도 얻은 trans(A) 및 trans(B)가 여전히 trans(A) > trans(B)를 만족하는 경우 공변성이라고 합니다. . 🎜🎜역변동은 정반대인 경우, 변경 trans(A)와 trans(B)는 trans(B) > trans(A)를 만족합니다. 역변화. 🎜🎜예를 들어, Java 배열이 공변적이라는 것은 누구나 알고 있습니다. A > B이면 A[] > B[]가 A[]에 할당될 수 있습니다. 예: 🎜Container<String> c = new Container<Object>(); // (1)编译报错Container<? super String> c = new Container<Object>(); // (2)编译通过
c.set("sss");// (3) 编译通过
String s = c.get();// (4) 编译报错复制代码
🎜그러나 Java의 제네릭은 다음과 같이 공분산을 충족하지 않습니다. 🎜public class Container<T> { private T item; public void set(T t) {
item = t;
} public T get() { return item;
}
}复制代码
🎜위 코드는 Object > Integer임에도 불구하고 제네릭이 공분산을 충족하지 않기 때문에 오류를 보고합니다. 따라서 List
Container<Object> c = new Container<String>(); // (1)编译报错Container<? extends Object> c = new Container<String>(); // (2)编译通过c.set("sss"); // (3)编译报错Object o = c.get();// (4)编译通过复制代码🎜함수 반환값 형식은 실제 반환값 형식의 값을 받습니다. B b 실제 반환값 형식은 함수 반환값 형식을 지정하는 것과 동일합니다. A a, 즉 B b 가 A a, 즉
A a = b
에 할당되면 A > B의 유형 관계가 충족되어야 합니다. 🎜🎜그러므로 어떤 종류의 과제라도 left type > right type, 즉 A > B를 만족해야 합니다. 🎜Java의 공분산과 반공변성🎜🎜이전의 기본 지식으로 공분산과 반공변성을 쉽게 설명할 수 있습니다. 🎜🎜클래스 A > 클래스 B, trans 변경 후에도 얻은 trans(A) 및 trans(B)가 여전히 trans(A) > trans(B)를 만족하는 경우 공변성이라고 합니다. . 🎜🎜역변동은 정반대인 경우, 변경 trans(A)와 trans(B)는 trans(B) > trans(A)를 만족합니다. 역변화. 🎜🎜예를 들어, Java 배열이 공변적이라는 것은 누구나 알고 있습니다. A > B이면 A[] > B[]가 A[]에 할당될 수 있습니다. 예: 🎜Container<String> c = new Container<Object>(); // (1)编译报错Container<? super String> c = new Container<Object>(); // (2)编译通过
c.set("sss");// (3) 编译通过
String s = c.get();// (4) 编译报错复制代码
🎜그러나 Java의 제네릭은 다음과 같이 공분산을 충족하지 않습니다. 🎜public class Container<T> { private T item; public void set(T t) {
item = t;
} public T get() { return item;
}
}复制代码
🎜위 코드는 Object > Integer임에도 불구하고 제네릭이 공분산을 충족하지 않기 때문에 오류를 보고합니다. 따라서 List
위 내용은 Java의 Kotlin 공분산과 반공분산에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

안전한 시험 브라우저
안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

DVWA
DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

드림위버 CS6
시각적 웹 개발 도구

Eclipse용 SAP NetWeaver 서버 어댑터
Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.
