I have an assignment and I'm stuck. The assignment is to write a generic class for this method:
public static void main(String[] args) {
ValueStore<Object> myStore1 = new ValueStore<Object>();
myStore1.set("Test");
myStore1.get();
///
ValueStore<Object> myStore2 = new ValueStore<Object>();
myStore2.set(myStore1);
myStore1 = myStore2.get();
}
I've come this far.
public class ValueStore<T> {
private T x;
public void set(T x) {
System.out.println(x);
}
public T get () {
return x;
}
}
I am able to print out mystore.set "test", but not the myStore2.set. And I don't understand why my teacher passed in a reference variable as a argument. When I do that I get ValueStore#15db9742 in the console. Or maybe thats the point?
Can someone explain why it says myStore2.set(myStore1);
myStore1 = myStore2.get(), what it should print and the logic behind it?
Thank you in advance. And sorry if my text is all messy. First time here.
I think currently you are just missing a line from your set() method, as in
public void set(T x) {
System.out.println(x);
this.x = x;
}
So that you would actually store the object.
I have commented a bit more to explain. The main point is that you can give a type to your ValueStore (in this example, String). This makes the typesystem aware that when you call get() on the valuestore, it gets a string in return. This is actually the entire point of generics. If you simply put object, only you know that the get method will return a String so you would have to cast it (as in the second example).
public static void main(String[] args) {
// Type your store with String, which is what generics is about.
ValueStore<String> myStore1 = new ValueStore<String>();
// Store a string in it.
myStore1.set("Test");
// Get the object, and the typesystem will tell you it's a string so you can print it.
System.out.println(myStore1.get());
///
ValueStore<Object> myStore2 = new ValueStore<Object>();
// Store your store.
myStore2.set(myStore1);
// The type system only knows this will return an Object class, as defined above.
// So you cast it (because you know better).
myStore1 = (ValueStore<String>) myStore2.get();
System.out.println(myStore1.get());
}
public class ValueStore<T> {
private T x;
public void set(T x) {
this.x = x;
}
public T get () {
return x;
}
}
This code prints the following:
test
test
Related
I'm encountering problems understanding how function are passed to methods as parameters.
Searching on StackOverflow and StackExchange has brought me to a solution using java.util.Functions
public void someFunction(Functions <int[], int[]> myFunction);
(source: https://codereview.stackexchange.com/questions/186972/passing-a-generic-function-as-parameter)
Although this solution seems good to me, I'm facing problem when I need to pass a function which is intended to do nothing. For better understanding, consider the following example:
public class Example {
//do stuffs
myFunction(null);
}
public class Manager {
public void myFunction(Function<int[], void> funcToPass) { // Can't specify void as return value!
//do stuff
if(funcToPass != null) { // can't replicate such behaviour
funcToPass(someParams)
}
}
}
Can someone help me acquiring clear understanding on this topic? Thank you so much.
If you want to describe a function that does not return a value, you can use the Void type. This is a standard Java class, but is intended for use in this situation.
E.g.
Function<String, Void> stringPrinter = s -> {
System.out.println(s);
return null; // must return some value, null is acceptable since there is no Void instance
};
The return null; is important since, from the compiler's point of view, Void is just like any other class (e.g. String, Integer, etc). It doesn't know that it represents the absence of a value, whereas it does know that a function that returns void does not have a return value.
This means the compiler still expects some return statement in your code, just as if it were returning an Integer, and so you must return null;
EDIT:
You may find, however, if you are strictly dealing with functions with no returns, you are better suited to use a Consumer<T>. For example:
Consumer<String> stringPrinter = s -> System.out.println(s);
stringPrinter.accept("hello");
or, using a method reference:
Consumer<String> stringPrinter = System.out::println;
stringPrinter.accept("hello");
You can use Reflection API to pass a void method as a reference e.g.
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception {
Class[] classParams = new Class[1];
classParams[0] = String.class;
Method method = Main.class.getMethod("hello", classParams);
Main obj = new Main();
System.out.println(new Main().getSum(obj, method, "world!", 10, 20));
}
public void hello(String msg) {
System.out.println("Hello " + msg);
}
int getSum(Object object, Method method, String msg, int x, int y) throws Exception {
Object[] objectParams = new Object[1];
objectParams[0] = msg;
method.invoke(object, objectParams);
return x + y;
}
}
Output:
Hello world!
30
I am wondering if ya'll can help me get a better grip on generics.
I have simplified this question as much as possible.
I am trying to save the element stored in a linked list in a variable called saveIt. I know LinkedList itself uses generics, so I want my variable to take up whatever data type is in the list. I believe LinkedList itself designates that type as E, but when I try to declare a variable as 'E saveIt' I get "cannot resolve symbol E."
public class Main {
public static void main(String[] args) {
// whatever goes here ...
}
void saveElement(LinkedList input) {
E saveIt = input.getFirst();
}
}
If I make the LinkedList then I can declare a variable as 'Integer saveIt' but that isn't what I want to do.
public class Main {
public static void main(String[] args) {
// whatever goes here ...
}
void saveElement(LinkedList<Integer> input) {
Integer saveIt = input.getFirst();
}
}
I considered declaring 'Object saveIt' but I'm not sure whether that is the right approach. The concept of datatype E obviously exists in Java, and isn't quite the same as Object (or is it?), so why can't I access it (or how can I access it)?
public class Main {
public static void main(String[] args) {
// whatever goes here ...
}
void saveElement(LinkedList input) {
Object saveIt = input.getFirst();
}
}
So, basic question is if I want to have my method address whatever datatype is in the list, how do I do that?
<E> void saveElement(LinkedList<E> input) {
E saveIt = input.getFirst();
}
You need to tell Java that E is a type parameter of your method -- it's like another thing that's being passed in! -- and that the LinkedList contains elements of type E.
Java question: Can someone please tell me why the statement obj.f1(); below does not work
and how to fix it? Thanks in advance.
class X{
void f1() {
System.out.println("XXX") ;
}
}
class Y extends X {
void f1(){
System.out.println("YYY");
}
}
public class Test {
public static void main(String[] args) {
Object obj = new Y();
obj.f1(); // why this does not work?
}
}
Assuming this is java, as you have not marked it as such:
You seem to be under the impression that java is dynamically type-checked, while in reality it is statically. This means that since you have declared obj as type Object, the compiler is rejecting your code because Object has no method f1().
The compiler doesn't care what you initialize it to, a local/field's delared type (the one in front) determines what can be called on it.
To fix this, you'll need to declare obj as a Y, like so: Y obj = new Y();.
I have 2 classes, one which extends the second one and overrides some of the methods of the parent. When I call fs.m(ff) I got a weird result, and I can't figure out why does it happen. type First fs shouldn't have access to class Second methods, even if we assigned a new Second object to them, unless we casted it like that - (Second) fs.m(ff). Could anyone please explain why does this code produce output "override"?
public class Main {
public static void main(String[] args) {
First ff = new First();
First fs = new Second();
Second ss = new Second();
System.out.println( fs.m(ff));
}
}
public class First {
public String m(First x){
return "default";
}
public String m(First x, First y){
return "default";
}
}
public class Second extends First{
public String m(Second x){
return "overload";
}
public String m(First x){
return "override";
}
public String m(First x, Second y){
return "???";
}
}
The method invoked for fs.m(ff) is determined by the runtime type of fs. That runtime type is Second, and since Second overrides the public String m(First x) method, that method is executed.
fs has access do the methods declared in First class, since it is of type First, but during runtime, the actual methods that get executed depend on whether those methods are overridden by the run-time type of the instance assigned to fs, which is Second.
Fs is actually pointing a Second Object (fs is a reference to an object of type Second).
So when you call fs.m(ff) it is actually calling the object on Second due to dynamic binding (override).
In JavaScript one can create and edit an object's functions on the fly. Is this possible with a Java object's methods? I am essentially wanting something like this:
public class MyObject{
private int x;
public MyObject(){x = 0;}
public myMethod(){}
}
MyObject foo = new MyObject();
and later call something along the lines of:
foo.myMethod = new method({x = 42;});
It's not directly possible, but you could try something like this:
public class MyObject {
private int x;
interface MyMethod {
void call();
}
public MyObject() {
x = 0;
}
public MyMethod myMethod = new MyMethod() {
#Override
public void call() {
x = 42;
}
};
}
You can't edit it in the way that you are trying to demonstrate above, the closest thing you could do to emulate it would be to intercept the method. The only way I could think of at the current moment is to use a MethodInterceptor found within the cglib library to intercept the method.
In Java you cannot do this like you would do it in Javascript.
But in Java you can achieve such an behavior using the Strategy pattern.
For example,
public interface Strategy {
void doSomething(MyObject obj);
}
public class BasicStrategy implements Strategy {
public void doSomething(MyObject obj) {
//do something
}
}
public class AnotherStrategy implements Strategy {
public void doSomething(MyObject obj) {
obj.setX(42);
}
}
public class MyObject {
private Strategy actualStrategy = new BasicStrategy();
private int x = 0;
public void executeStrategy() {
actualStrategy.doSomething(this);
}
public void setStrategy(Strategy newStrategy) {
actualStrategy = newStrategy;
}
public void setX(int x) {
this.x = x;
}
}
You can alter the behavior of the method at runtime using the following code.
MyObject obj = new MyObject();
obj.setStrategy(new AnotherStrategy());
obj.executeStrategy();
Yes, it's theoretically possible, but you don't want to do it. This sort of thing is black magic, and if you need to ask the question, you're several years from being ready to work with it.
That said, what you're trying to accomplish may be workable with the Strategy design pattern. The idea here is that you define an interface that has the method(s) you need to swap out (say, calculate()), and the class whose behavior you want to change has a field of that interface. You can then modify the contents of that field.
public interface Calculator {
double calculate(double x, double y);
}
public class MathStuff {
private Calculator calc;
...
public void doStuff() {
...
result = calc.calculate(x, y);
...
}
}
public class Add implements Calculator {
public double calculate(double x, double y) {
return x + y;
}
}
You cannot do this. In java new method is made to return the instance of class Object, not methods. And one thing is to understand is Javascript is an functional programming language and Java is a object oriented language. You cannot treat a method as object in java, also it breaks the security of java encapsulation.