Skip to content

Commit 186bf52

Browse files
update README.md
1 parent f4defea commit 186bf52

File tree

1 file changed

+134
-39
lines changed

1 file changed

+134
-39
lines changed

README.md

Lines changed: 134 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,195 @@
11
# Java Variance
22

3-
![Build Status](https://img.shields.io/github/workflow/status/bldl/java-variance/CI) ![License](https://img.shields.io/github/license/bldl/java-variance)
3+
![Build Status](https://img.shields.io/github/workflow/status/bldl/java-variance/maven) ![License](https://img.shields.io/github/license/bldl/java-variance)
44

55
## Description
66

7-
This is a project that incorporates Java annotations in order to allow specification of different generic parameter variances.
7+
This project provides Java annotations that enable fine-grained specification of variance for class generics, improving flexibility in generic programming.
88

99
## Table of Contents
1010

1111
- [Installation](#installation)
12-
- [Prerequisites](#prerequisites)
1312
- [For maven users](#for-maven-users)
14-
- [For grade users](#for-gradle-users)
1513
- [For other users](#for-other-users)
14+
- [Background](#background)
15+
- [What is variance](#what-is-variance)
16+
- [Types of variance](#types-of-variance)
1617
- [Usage](#usage)
17-
- [Subsection](#subsection)
18+
- [Annotations](#annotations)
19+
- [Output](#output)
1820
- [Contributing](#contributing)
1921

2022
## Installation
2123

22-
### Prerequisites
24+
### For Maven users
2325

24-
### For maven users
26+
Add the following dependency to your pom.xml
2527

26-
<!-- TODO: Add when project is published to maven central -->
28+
```xml
29+
<dependency>
30+
<groupId>io.github.bldl</groupId>
31+
<artifactId>java-variance</artifactId>
32+
<version>LATEST</version>
33+
</dependency>
34+
```
2735

28-
### For gradle users
36+
### For other users
2937

30-
<!-- TODO: Add when project is published to maven central -->
38+
Using Git Submodules
39+
If your project does not use Maven or Gradle, but you still want to use the annotations provided by this library, you can include it as a Git submodule. Here's how:
3140

32-
### For other users
41+
**1. Add the repository as a submodule:**
3342

34-
```bash
35-
$ git submodule add https://github.com/bldl/java-variance
43+
```sh
44+
git submodule add https://github.com/bldl/java-variance
3645
```
3746

38-
## What is variance
47+
**2. Initialize and update the submodule:**
48+
49+
```sh
50+
git submodule update --init
51+
```
52+
53+
**3. Add the submodule to your classpath in your project setup. For example:**
54+
55+
- If using an IDE, configure the submodule to be a source directory.
56+
- If using a custom build script, ensure the submodule's output is included in the compilation step.
3957

40-
# Variance in Generic Programming
58+
## Background
4159

42-
**Variance** in Generic Programming refers to how subtyping between more complex generic types (like `List<T>`) relates to subtyping between their type parameters (like `T`). It determines whether type relationships are preserved, reversed, or invariant when generic types are involved.
60+
### What is variance
4361

44-
## Types of Variance
62+
**Variance** in Generic Programming refers to how subtyping between more complex generic types (like `List<T>`) relates to subtyping between their type parameters (like `T`). It determines whether type relationships are preserved, reversed, or discarded for each type parameter.
4563

46-
### 1. **Covariance**
64+
### Types of Variance
65+
66+
**1. Covariance**
4767

4868
Covariance allows a generic type to be substituted with another generic type that has a more specific (derived) type parameter.
4969

50-
- Example: `List<Animal>` can accept `List<Dog>` if `Dog` is a subtype of `Animal`.
51-
- Used when a generic type is only **producing** (out) values.
52-
- Marked with **`out`** in Kotlin or achieved with `? extends` in Java.
70+
- Example: `List<Animal>` is a subtype of `List<Dog>` if `Dog` is a subtype of `Animal`.
71+
- Used when a generic type is only **producing** (out) values. That is the generic type is not part of any non-private variables or method parameters.
5372

54-
### 2. **Contravariance**
73+
**2. Contravariance**
5574

5675
Contravariance allows a generic type to be substituted with another generic type that has a more general (base) type parameter.
5776

58-
- Example: `List<Dog>` can accept `List<Animal>` if `Animal` is a supertype of `Dog`.
59-
- Used when a generic type is only **consuming** (in) values.
60-
- Marked with **`in`** in Kotlin or achieved with `? super` in Java.
77+
- Example: `List<Dog>` is a sybtype of `List<Animal>` if `Animal` is a supertype of `Dog`.
78+
- Used when a generic type is only **consuming** (in) values. That is the generic type is not part of any non-private variables or method return types.
79+
80+
**3. Bivariance**
81+
82+
Bivariance allows a generic type to be substituted with another generic type regardless of the relationship between their type parameters. This means a generic type can accept both more specific (derived) and more general (base) type parameters interchangeably.
83+
84+
- Example: Both `List<Dog>` is a sybtype of `List<Animal>` and `List<Animal>` is a subtype of of `List<Dog>` if Dog is a subtype of Animal.
85+
- Practical Use: Bivariance is generally unsafe in strongly typed systems because it disregards type safety. It might be allowed in certain scenarios where type constraints are relaxed for specific purposes, such as event handlers or certain dynamic language constructs.
86+
- Drawbacks: Since it permits type substitution in both directions, it can lead to runtime errors if the system tries to enforce incompatible operations.
6187

62-
### 3. **Invariance**
88+
**4. Invariance**
6389

6490
Invariance means no substitution is allowed between different generic types, even if their type parameters have a subtype relationship.
6591

6692
- Example: `List<Animal>` and `List<Dog>` are entirely distinct and incompatible.
6793
- This is the default in many languages, like Java's generics.
6894

69-
---
70-
71-
## Key Insight
72-
73-
Covariance and contravariance depend on how the generic type uses its type parameter: **producing outputs** (covariance) or **consuming inputs** (contravariance). Invariant types neither allow flexibility.
95+
## Usage
7496

7597
### Annotations
7698

77-
There are currently three annotations provided by this project: MyVariance, Covariant and Contravariant. With these you are able to annotate type parameters for classes in order to
99+
There are currently three annotations provided by this project: MyVariance, Covariant and Contravariant. With these you are able to annotate type parameters for classes in order to specify fine grained variance.
78100

79-
#### MyVariance
101+
### MyVariance
80102

81103
MyVariance is the most customizable one, and allows you to experiment with different types of variance. With this one there are several parameters you can provide to specify what variance rules should apply:
82104

83-
| Parameter | Description | Possible values |
84-
| ---------- | ----------------------------------------- | ----------------------------------- |
85-
| `variance` | Specifies which variance to use | COVARIANT, CONTRAVARIANT, INVARIANT |
86-
| `depth` | How deep subtyping goes | Integer value ≥ 0 |
87-
| `strict` | Whether strict checks should be performed | `true`, `false` |
105+
INVARIANT,
106+
COVARIANT,
107+
CONTRAVARIANT,
108+
BIVARIANT,
109+
SIDEVARIANT
110+
111+
| Parameter | Description | Possible values |
112+
| ---------- | ------------------------------- | ----------------------------------------------------------- |
113+
| `variance` | Specifies which variance to use | COVARIANT, CONTRAVARIANT, INVARIANT, BIVARIANT, SIDEVARIANT |
114+
| `depth` | How deep subtyping goes | Integer value ≥ 0 |
115+
| `strict` | Whether | `true`, `false` |
88116

89117
#### Covariant
90118

91119
Covariant is a specific instance of MyVariance. It's intended to inline with the semantics of traditional covariance. It acts as MyVariance with `variance` set to `COVARIANT`, `depth` as infinite and `strict` to `true`.
92120

121+
<details>
122+
<summary>
123+
Code example
124+
</summary>
125+
126+
```java
127+
public class ImmutableList<@Covariant T> {
128+
List<T> underlyingList = new ArrayList<>();
129+
130+
public ImmutableList(Iterable<T> initial) {
131+
initial.forEach(e -> underlyingList.add(e));
132+
}
133+
134+
public int size() {
135+
return underlyingList.size();
136+
}
137+
138+
public boolean isEmpty() {
139+
return size() == 0;
140+
}
141+
142+
public boolean contains(Object o) {
143+
return underlyingList.contains(o);
144+
}
145+
146+
public Iterator<T> iterator() {
147+
return underlyingList.iterator();
148+
}
149+
150+
public Object[] toArray() {
151+
return underlyingList.toArray();
152+
}
153+
154+
public T get(int i) {
155+
return underlyingList.get(i);
156+
}
157+
158+
}
159+
```
160+
161+
</details>
162+
93163
#### Contravariant
94164

95165
Contravariant, similarly to Covariant, aims to inline with the semantics of traditional contravariance. It acts as MyVariance with `variance` set to `CONTRAVARIANT`, `depth` as infinite and `strict` to `true`.
96166

97-
### Subsection
167+
<details>
168+
<summary>
169+
Code example
170+
</summary>
171+
172+
```java
173+
class Pair<@Contravariant X, @Contravariant Y> {
174+
private X first;
175+
private Y second;
176+
177+
public Pair(X first, Y second) {
178+
this.first = first;
179+
this.second = second;
180+
}
181+
182+
public void setFirstElement(X first) {
183+
this.first = first;
184+
}
185+
186+
public Y setSecondElement(Y second) {
187+
this.second = second;
188+
}
189+
}
190+
```
191+
192+
</details>
98193

99194
## Contributing
100195

0 commit comments

Comments
 (0)