I have multiple different classes Class1, Class2, Class3.
Each class has different variables and getters for them.
public class Class1 {
private String var1_1;
private String var1_2;
private String var1_3;
public String getVar1_1() { return var1_1;}
public String getVar1_2() { return var1_2;}
public String getVar1_3() { return var1_3;}
}
public class Class2 {
private String var2_1;
private String var2_2;
private String var2_3;
public String getVar2_1() { return var2_1;}
public String getVar2_2() { return var2_2;}
public String getVar2_3() { return var2_3;}
}
public class Class3 {
private String var3_1;
private String var3_2;
private String var3_3;
public String getVar3_1() { return var3_1;}
public String getVar3_2() { return var3_2;}
public String getVar3_3() { return var3_3;}
}
How can I write method which takes List of objects and getters(functions) as a method parameters?
For example:
List<Class1> list1 = //doesn't matter
List<Class2> list2 = //doesn't matter
List<Class3> list3 = //doesn't matter
generateRows(list1, Class1::getVar1_1, Class1::getVar1_3);
generateRows(list2, Class2::getVar2_1, Class2::getVar2_2, Class2::getVar2_3);
generateRows(list3, Class3::getVar3_1, Class3::getVar3_2);
Method
public void generateRows(List<T> list, /*???Something???*/... getters) {
for(T object: list) {
/*How to use getters to print?*/
/*System.out.println(obj.firtsGetter())*/
}
}
What I should write instead of ???Something???. Something like Function<T, String> or Consumer<T>? And how can I use getters in method?
You need to wrap the method calls in a Function. A Consumer, or another FunctionalInterface might do the trick as well, depending on your needs.
Then you need to have your method accept varargs of this function.
public static <T> void generateRows(List<T> list, Function<T, String>... getters) {
for (T object : list) {
for (Function<T, String> getter : getters) {
System.out.println(getter.apply(object));
}
}
}
Function will accept argument of type T and return a String. T can be anything - Class1, Class2, etc., as long you can return a string from this object - that means to have a getter method returning String in your case.
First you can defined a interface eg:
interface Get{
String getVar1();
String getVar2();
String getVar3();
}
Second All of classes implemente it:
class Class2 implements Get{
private String var2_1;
private String var2_2;
private String var2_3;
public String getVar1() { return var2_1;}
public String getVar2() { return var2_2;}
public String getVar3() { return var2_3;}
}
Third:
public void generateRows(List<T> list, Get ...getters) {
for(T object: list) {
/*How to use getters to print?*/
/*System.out.println(obj.firtsGetter())*/
}
}
Related
I'm attempting to create an enum whose constructor accepts an object whose base class is a generic class.
I seem to be unable to fetch the underlying generic type from within the enum however, Object gets returned instead of T.
Is there a way to do this?
abstract public class Field<T> {
abstract public T get();
}
public class IntegerField extends Field<Integer> {
public Integer get() {
return 5;
}
}
public class StringField extends Field<String> {
public String get() {
return "5";
}
}
public enum Fields {
INTEGER (new IntegerField()),
STRING (new StringField());
private final Field<?> field; // <<--- I can't have Field<T>, enum's can't be generic. :(
<T> Fields(Field<T> field) {
this.field = field;
}
public <T> T get() {
return field.get(); // <<--- Returns Object, not T
}
}
The issue is that enums can't be generically typed so even if you cast that get call ((T) field.get()) you won't have type safety because it will agree with any assignment (you could compile this successfully for instance: boolean b = Fields.INTEGER.get()).
Just use constants instead:
public final class Fields {
public static final Field<Integer> INTEGER = new IntegerField();
public static final Field<String> STRING = new StringField();
}
Why do you think an enum is preferable to this?
public final class Fields {
public static final Field<Integer> INTEGER = new IntegerField();
public static final Field<String> STRING = new StringField();
//private ctor
}
or if you prefer
public final class Fields {
public static Field<Integer> integerField() {
return new IntegerField();
}
public static Field<String> stringField() {
return new StringField();
}
//private ctor
}
Why would I want to call Fields.INTEGER.get() when I can just use Fields.INTEGER?
I have this Event class that I’d like to make more generic, so I can return other types than just User, Is there a way of auto casting inside this event class or should I do it everytime outside of it?.
Do you have suggestions?
What I have
public class Event {
protected String name;
protected Pair<String, User> event;
public String getName() {
return event.first;
}
public User getData() {
return event.second;
}
public Event(String name, User data) {
event = Pair.create(name, data);
}
}
What I want
public class Event<T> {
protected String name;
protected Pair<String, T> event;
public String getName() {
return event.first;
}
public T getData() {
return event.second; //cast to type
}
public Event(String name, T data) {
event = Pair.create(name, data);
}
}
When you create an instance of Event<User>, T gets automatically "substituted" to User
So public T getData() actually returns an User and there is no need for casting
I'm not sure how you defined Pair, but the following works without any casting required:
public class Pair<F,S>
{
F first;
S second;
public Pair (F first, S second) {
this.first=first;
this.second=second;
}
public static <F,S> Pair<F,S> create (F first, S second) {
return new Pair<F,S> (first,second);
}
}
public class Event<T> {
protected String name;
protected Pair<String, T> event;
public String getName() {
return event.first;
}
public T getData() {
return event.second;
}
public Event(String name, T data) {
event = Pair.create (name, data); // note you can use the Pair constructor directly
// instead of calling the static create method
}
}
Which can be used, for example, like this:
Event<Integer> intEvent = new Event<> ("name", 5);
Integer data = intEvent.getData ();
I have two classes:
class a {
public static int var;
private int getVar() {
return var; //Yes
}
private void setVar(int var) {
a.var = var; //Yes
}
}
class b {
private int getVar() {
return a.var; //Yes
}
private void setVar(int var) {
a.var = var; //No
}
}
Q: Can i make modifiable member only from his class, for other classes would be constant ?
No, the public access modifier basically allows you to modify the value of the reference from anywhere in your code base.
What you can do is have a private or less-restricted access modifier according to your specific needs, and then implement a getter, but no setter.
In the latter case, remember to add some logic to prevent mutable objects, such as collections, from being mutated.
Example
class Foo {
// primitive, immutable
private int theInt = 42;
public int getTheInt() {
return theInt;
}
// Object, immutable
private String theString = "42";
public String getTheString() {
return theString;
}
// mutable!
private StringBuilder theSB = new StringBuilder("42");
public StringBuilder getTheSB() {
// wrapping around
return new StringBuilder(theSB);
}
// mutable!
// java 7+ diamond syntax here
private Map<String, String> theMap = new HashMap<>();
{
theMap.put("the answer is", "42");
}
public Map<String, String> getTheMap() {
// will throw UnsupportedOperationException if you
// attempt to mutate through the getter
return Collections.unmodifiableMap(theMap);
}
// etc.
}
Just remove setter and make variable private. Then other class only can read the value stetted.
public class a {
private static int var=2;
public static int getVar() {
return var;
}
}
But when you come to Java reflection there is no such protection.
The answer Is NO you can't make a public static variable only modified from its class you can make the variable private and has only public getter or you can add setter private
I want to define map in Java, which keys are enums, and types of value depend of key. For example, suppose that we have following enum type:
enum KeyType {
HEIGHT(Integer.class),
NAME(String.class),
WEIGHT(Double.class)
// constructor and getter for Class field
}
and some map:
Map< KeyType, Object > map = new EnumMap<>(KeyType.class);
Is there any simple and safe way to write generic method:
public < T > T get(KeyType key) {
//...
}
that would get value from that map and cast it to corresponding with type class?
UPDATE!!!:
With this in mind:
enum KeyType {
//your enums ...
private final Class val;
//constructor ...
//and generic(!) access to the class field:
<T> Class<T> val() {
return val;
}
}
...this is possible:
public <T> T get(KeyType key) {
return (T) key.val().cast(map.get(key));
}
Your map definition would need to be
Map< KeyType, ?> map = new EnumMap<>(KeyType.class);
If you specify Object as a generic type, only actual instances of Object are allowed, not sub-types.
I don't believe there's any straight forward, generic way (no pun intended) to do what you want. You would need to create some mapping function that translates the object to the correct type based on the enum.
You can't do it with enums. But you could write a "fake" enum (the way Java code did it before Java 1.5, with private constructors and public static instances), and attach a generic type to each constant:
import java.io.Serializable;
import java.util.Map;
public final class KeyType<T>
implements Serializable {
private static final long serialVersionUID = 1;
public static final KeyType<Integer> HEIGHT =
new KeyType<>("HEIGHT", Integer.class);
public static final KeyType<String> NAME =
new KeyType<>("NAME", String.class);
public static final KeyType<Double> WEIGHT =
new KeyType<>("WEIGHT", Double.class);
private static final KeyType<?>[] allValues = {
HEIGHT, NAME, WEIGHT
};
/** #serial */
private final String name;
/** #serial */
private final Class<T> type;
private KeyType(String name,
Class<T> type) {
this.name = name;
this.type = type;
}
public String name() {
return name;
}
public Class<T> getType() {
return type;
}
#Override
public String toString() {
return name();
}
public static KeyType<?>[] values() {
return allValues.clone();
}
public static KeyType<?> valueOf(String name) {
for (KeyType<?> value : allValues) {
if (value.name.equals(name)) {
return value;
}
}
throw new IllegalArgumentException("No such value: \"" + name + "\"");
}
#Override
public boolean equals(Object obj) {
return (obj instanceof KeyType &&
this.name.equals(((KeyType<?>) obj).name));
}
#Override
public int hashCode() {
return name.hashCode();
}
public T getValue(Map<KeyType<?>, ?> map) {
return type.cast(map.get(this));
}
}
I'm a bit confused with subclasses.
Here's my code:
public class MedHistory {
private String grafts;
private String allergies;
private String diseases;
private String surgeries;
private String medicalTreatment;
//Constructors (#2)
public MedHistory(String allergies, String diseases, String grafts,
String treatments, String surgeries) {
this.allergies=allergies;
this.diseases=diseases;
this.grafts=grafts;
this.medicalTreatment=treatments;
this.surgeries=surgeries;
}
public MedHistory() {
this.allergies="";
this.diseases="";
this.grafts="";
this.medicalTreatment="";
this.surgeries="";
}
//Getters
public String getGrafts() {
return grafts;
}
public String getAllergies() {
return allergies;
}
public String getDiseases() {
return diseases;
}
public String getSurgeries() {
return surgeries;
}
public String getMedicalTreatment() {
return medicalTreatment;
}
//Setters
public void setGrafts(String grafts) {
this.grafts = grafts;
}
public void setAllergies(String allergies) {
this.allergies = allergies;
}
public void setDiseases(String diseases) {
this.diseases = diseases;
}
public void setSurgeries(String surgeries) {
this.surgeries = surgeries;
}
public void setMedicalTreatment(String medicalTreatment) {
this.medicalTreatment = medicalTreatment;
}
public class FemMedHistory extends MedHistory {
private List<Birth> births = new ArrayList<Birth>();
//Constructors (#2)
public FemMedHistory(String allergies, String diseases, String grafts,String treatments, String surgeries, List<Birth> birthlist) {
super(allergies,allergies,grafts,treatments,surgeries);
this.births=birthlist;
}
public FemMedHistory() {
super();
this.births=null;
}
//Getter
public List<Birth> getBirths() {
return this.births;
}
//Setter
public void setBirths(List<Birth> list) {
this.births=list;
}
}
}
When I try to create an new FemMedHistory object like this:
List<Birth> list = new ArrayList<Birth>();
list.add(new Birth(new GregorianCalendar(2011,4,10),"kaisariki",4));
FemMedHistory female = new FemMedHistory("allergia2","astheneia2","emvolia2","farmekeutiki agwgi2", "xeirourgeia2", list);
I get the error:
No enclosing instance of type MedHistory is accessible. Must qualify
the allocation with an enclosing instance of type MedHistory (e.g.
x.new A() where x is an instance of MedHistory).
So, which is the right way to use a subclass?
When you declare a nested class it only available through the Outer class.
To access it outside, you will need to either make the FemMedHistory class static.
public static class FemMedHistory extends MedHistory {...}
access it through the MedHistory class
MedHistory.FemMedHistory myMedHistory = ...
or declare it in it's own Java file.
You have declared your subclass as an inner class, which means that you can't create an instance of it without first creating an instance of the containing class.
The most common way to solve this is to declare it as a separate class, which would get rid of your error.
Long story short: cut all the FemMedHistory code and paste it into FemMedHistory.java. The way it is now you have involved Java concepts which you have not yet mastered. Also, that class really does belong in a separate file.