Skip to content

Commit 52b9365

Browse files
committed
More reflection
1 parent 101ffc7 commit 52b9365

File tree

8 files changed

+172
-4
lines changed

8 files changed

+172
-4
lines changed

src/SUMMARY.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -603,10 +603,12 @@ Make them do one. -->
603603
- [Reflection](./reflection.md)
604604
- [Class Objects](./reflection/class_objects.md)
605605
- [Get all Fields](./reflection/get_all_fields.md)
606-
- [Get a Field]()
607-
- [Set a Field]()
608-
- [Get a Method]()
609-
- [Call a Method]()
606+
- [Get a Field](./reflection/get_a_field.md)
607+
- [Read from a Field](./reflection/read_from_a_field.md)
608+
- [Write to a Field](./reflection/write_to_a_field.md)
609+
- [Get all Methods](./reflection/get_all_methods.md)
610+
- [Get a Method](./reflection/get_a_method.md)
611+
- [Invoke a Method](./reflection/invoke_a_method.md)
610612
- [Get a Constructor]()
611613

612614
- [Annotations](./annotations.md)

src/reflection/get_a_field.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Get a Field
2+
3+
You can retrieve a single field by its name using `getField`. If there
4+
is no field with that name it will throw a `NoSuchFieldException`.
5+
6+
```java
7+
import java.lang.reflect.Field;
8+
9+
class Main {
10+
void main() throws NoSuchFieldException {
11+
Class<Drink> drinkClass = Drink.class;
12+
13+
Field nameField = drinkClass.getField("name");
14+
System.out.println(nameField);
15+
}
16+
}
17+
18+
class Drink {
19+
public String name;
20+
public boolean caffeinated;
21+
}
22+
```
23+
24+
And if you need to access a field that might be non-public you can use `getDeclaredField`.
25+
26+
```java,panics
27+
import java.lang.reflect.Field;
28+
29+
class Main {
30+
void main() throws NoSuchFieldException {
31+
Class<Soup> soupClass = Soup.class;
32+
33+
Field hasVeggiesField = soupClass.getDeclaredField("hasVeggies");
34+
System.out.println(hasVeggiesField);
35+
36+
// Will fail. getField won't see hasVeggies
37+
soupClass.getField("hasVeggies");
38+
}
39+
}
40+
41+
class Soup {
42+
public String name;
43+
boolean isChicken;
44+
private boolean hasVeggies;
45+
}
46+
```
47+

src/reflection/get_a_method.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Get a Method

src/reflection/get_all_methods.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Get all Methods

src/reflection/get_methods.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Get Methods

src/reflection/invoke_a_method.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Invoke a Method
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Read from a Field
2+
3+
Once you have a `Field` object you can use its `get` method to read the value of that field
4+
from an object. This will throw an `IllegalAccessException` if you try to read a field you
5+
are not allowed to.[^permission]
6+
7+
```java
8+
import java.lang.reflect.Field;
9+
10+
class Main {
11+
void main() throws IllegalAccessException {
12+
Class<Drink> drinkClass = Drink.class;
13+
14+
Field nameField;
15+
try {
16+
nameField = drinkClass.getField("name");
17+
} catch (NoSuchFieldException e) {
18+
throw new RuntimeException(e); // Should have this field
19+
}
20+
21+
var soda = new Drink("Soda", true);
22+
var water = new Drink("Water", false);
23+
24+
System.out.println(nameField.get(soda));
25+
System.out.println(nameField.get(water));
26+
}
27+
}
28+
29+
class Drink {
30+
public String name;
31+
public boolean caffeinated;
32+
33+
Drink(String name, boolean caffeinated) {
34+
this.name = name;
35+
this.caffeinated = caffeinated;
36+
}
37+
}
38+
```
39+
40+
[^permission]: The rules for this go a bit beyond "you cannot read private fields."

src/reflection/write_to_a_field.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Write to a Field
2+
3+
Similarly, you can write to a field using the `.set` method on a `Field` object.
4+
This will also throw `IllegalAccessException` if its not something you are allowed to do.
5+
6+
```java
7+
import java.lang.reflect.Field;
8+
9+
class Main {
10+
void main() throws IllegalAccessException {
11+
Class<Drink> drinkClass = Drink.class;
12+
13+
Field caffeinatedField;
14+
try {
15+
caffeinatedField = drinkClass.getField("caffeinated");
16+
} catch (NoSuchFieldException e) {
17+
throw new RuntimeException(e);
18+
}
19+
20+
var water = new Drink("Water", false);
21+
22+
// You can put drugs in anything you set your mind to, kids
23+
caffeinatedField.set(water, true);
24+
25+
System.out.println(caffeinatedField.get(water));
26+
}
27+
}
28+
29+
class Drink {
30+
public String name;
31+
public boolean caffeinated;
32+
33+
Drink(String name, boolean caffeinated) {
34+
this.name = name;
35+
this.caffeinated = caffeinated;
36+
}
37+
}
38+
```
39+
40+
If you try to set a field to the wrong type of value - like setting a `boolean` field to have a `String` value -
41+
you will get an `IllegalArgumentException`. Unlike `NoSuchFieldException` and `IllegalAccessException` this is an
42+
unchecked exception, so you do not need to explicitly account for it.
43+
44+
```java
45+
import java.lang.reflect.Field;
46+
47+
class Main {
48+
void main() throws IllegalAccessException {
49+
Class<Drink> drinkClass = Drink.class;
50+
51+
Field caffeinatedField;
52+
try {
53+
caffeinatedField = drinkClass.getField("caffeinated");
54+
} catch (NoSuchFieldException e) {
55+
throw new RuntimeException(e);
56+
}
57+
58+
var soda = new Drink("Soda", true);
59+
60+
caffeinatedField.set(soda, "yes, very much so");
61+
62+
System.out.println(caffeinatedField.get(soda));
63+
}
64+
}
65+
66+
class Drink {
67+
public String name;
68+
public boolean caffeinated;
69+
70+
Drink(String name, boolean caffeinated) {
71+
this.name = name;
72+
this.caffeinated = caffeinated;
73+
}
74+
}
75+
```

0 commit comments

Comments
 (0)