Class for Strong References in Java, for anonymous classes - java

I want a hard reference class in my Java code, but, of course, there isn't one. Is there some other way to do what I want, or should I make my own class?
This comes up with anonymous classes in methods where I want the anonymous class to set the return value for the method.
For example, given
interface Greeting {
void greet();
}
I want code like the following:
// Does not compile
static void hello(final String who) {
String returnValue;
Greeting hello = new Greeting() {
public void greet() {
returnValue = "hello" + who;
}
};
hello.greet();
System.out.println(returnValue);
}
I can fake it using a list:
static void hello(final String who) {
final List<String> returnValue = new ArrayList<String>();
Greeting hello = new Greeting() {
public void greet() {
returnValue.add("hello" + who);
}
};
hello.greet();
System.out.println(returnValue.iterator().next());
}
But I want to not use a list. I can write a StrongReference class that solves this:
static class StrongReference<T> {
private T referent;
public void set(T referent) {
this.referent = referent;
}
public T get() {
return referent;
}
}
which makes my method clearer:
static void hello(final String who) {
final StrongReference<String> returnValue = new StrongReference<String>();
Greeting hello = new Greeting() {
public void greet() {
returnValue.set("hello" + who);
}
};
hello.greet();
System.out.println(returnValue.get());
}
For my contrived example, I could have greet() return a String, but I'm working with much more complex classes, where the setting is deep within a database call that the base class manages. The instances have many different types they want to return, so I've just been using the List trick.
My questions are: Is there a better way to do this? What's wrong with my StrongReference class? Has anyone written a StrongReference in a library somewhere?

If you want something from the standard API, perhaps an AtomicReference would do?
It has void set(V value) and a V get() methods. Unless you have multiple threads involved, just see the synchronization mechanism as a bonus ;-)

A common idiom
final String[] result = { null };
result[0] = ...;

Looks good but I think you should make some kind of synchronization since another thread might set the value.

Related

Passing a null function to java function as argument

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

Store references to instance methods in a static context

I would like to have a static map where the values are instance methods. Someting like:
public class MyClass {
static Map<MyEnum, Consumer<String>> methodMapping;
static {
methodMapping = new EnumMap<>(MyEnum.class);
methodMapping.put(MyEnum.FIRST, MyClass::firstMethod);
methodMapping.put(MyEnum.SECOND, MyClass::secondMethod);
}
void firstMethod(String param) {
...
}
void secondMethod(String param) {
...
}
}
This gives me an error saying "Non-static method cannot be referenced from a static context". I understand why this would be a problem if I would try to call the methods from the static context, but isn't it possible from an instance method to retrieve the method from the map and pass it this? Like:
MyClass.methodMapping.get(MyEnum.FIRST).accept(this, "string");
This is solvable as easy as changing Consumer to BiConsumer, turning the receiver instance of MyClass to a parameter of the function:
public class MyClass {
static Map<MyEnum, BiConsumer<MyClass,String>> methodMapping;
static {
methodMapping = new EnumMap<>(MyEnum.class);
methodMapping.put(MyEnum.FIRST, MyClass::firstMethod);
methodMapping.put(MyEnum.SECOND, MyClass::secondMethod);
}
void firstMethod(String param) {
...
}
void secondMethod(String param) {
...
}
void callTheMethod(MyEnum e, String s) {
methodMapping.get(e).accept(this, s);
}
}
You initialize methodMapping in a static initialization block. At that point, your instance methods can't be referred to yet because you haven't called new MyClass() yet.
You could fix this by either making your methods static, or moving the methodMapping initialization from the static block to a constructor.
PS: The keyword static can be omitted from the initialization block
isn't it possible from an instance method to retrieve the method from the map and pass it this
No. A Consumer only has a single parameter accept() method, so there's no such thing as "passing this at calling time".
You need an instance when creating the method reference, so this questions boils down to "can't call instance method from a static context".
It seems that you don't understand that
static Map<MyEnum, Consumer<String>> methodMapping;
static {
does exactly that, trying to call the methods from the static context where they don't exist.
The key thing to understand here: you intend to create a method reference; and a method reference needs some object to invoke that method on. Thus there is no "delaying"; there is no way in java to express "wait for this to be meaningful"; or in other words: there is no way in a static context to express: "you will be used in a non-static context later on; and then pick the corresponding this from there".
The key is to defer the specification of this or to be more specific: The particular instance on which a method is to be called. So instead of storing method references directly we store functions that accept an instance and return a method reference for that instance.
MyClass.java
public class MyClass {
static Map<MyEnum, Function<MyClass, Consumer<String>>> methodMapping;
static {
methodMapping = new EnumMap<>(MyEnum.class);
methodMapping.put(MyEnum.FIRST, t -> t::firstMethod);
methodMapping.put(MyEnum.SECOND, t -> t::secondMethod);
}
private String id;
public MyClass(String id) {
this.id = id;
}
void firstMethod(String param) {
System.out.println(id + ", 1st method, " + param);
}
void secondMethod(String param) {
System.out.println(id + ", 2nd method, " + param);
}
void dispatchMethod(MyEnum myEnum, String param) {
methodMapping.get(myEnum).apply(this).accept(param);
}
}
Main.java
public class Main {
public static void main(String[] args) {
MyClass instance = new MyClass("MyInstance");
MyClass.methodMapping.get(MyEnum.FIRST).apply(instance).accept("Using mapping directly");
instance.dispatchMethod(MyEnum.SECOND, "Using dispatch method");
}
}
Ideally methodMapping should be shielded against direct access from other classes so I'd suggest taking the dispatchMethod approach and making methodMapping private and immutable.

Encapsulating what doesn't vary?

It's a common practice to encapsulate code that often changes. In fact, it is often in the form of using an object to delegate the varying logic to. A sample would be the following:
public class SampleClass {
Object obj = new ObjectWithVaryingMethod();
public SampleClass(Object obj){
this.obj=obj;
}
public String getString(){
return obj.toString();
}
public static void main(String args[]){
SampleClass sampleClass=new SampleClass(new ObjectWithVaryingMethod());
System.out.println(sampleClass.getString());
}
}
class ObjectWithVaryingMethod{
#Override
public String toString(){
return "Hi";
}
}
Can you suggest what problems I may encounter when "encapsulation" is done on what doesn't vary? I find it to be a good coding conduct when the main class itself is the one that is often subject to change or improvement. A sample would be the following. In this second case, retrieving "Hi", which is the part that doesn't vary, was "encapsulated" in another class.
public class SampleVaryingClass {
public static void main(String args[]) {
//here I may opt to print getHi's value on sysout or on a dialog
System.out.println(ObjectWithNonVaryingMethod.getHi());
}
}
In a completely different class...
public class ObjectWithNonVaryingMethod {
private static final String hi = "Hi";
//"Hi" should always be returned
public static String getHi() {
return hi;
}
}
Can you give some pro's and con's on doing this?
Both code cannot be compared each other. One is static, another one isn't. I hope you understand the concept of encapsulating the object in the first code. Here is the pros and cons for the second one. Remember that static is "generally" bad, and do not support concurrency by default.
pros:
With getHi, you are keeping the string field private, meaning that it cannot be set from other source
Say that you need to do setHi from other source, you can add several guard clauses for it. This is called defensive programming.
public static setHi(String input){
if(input == null) { input = ""; } // can throw exception instead
hi = input;
}
cons:
It is static, needless to say
You don't get any advantage other than guard clauses. If your class is not static, you can swap it with other class implementing same interface, or other class inherited from that class.

Allowing object construction only from some packages

I work on a game-like system. Users can submit .class and .java files for customized behaviour. Some objects are delivered to the user via callback, but if the user can construct these object himself (with custom parameters), it would mean an advantage to him. I will disallow reflection for the user and seal my packages. I can get this working if I abandon all package structure (and make the constructors package-private), but I would like not to do so.
Here is an example:
sscce.mycode.a.SomeClass.java:
package sscce.mycode.a;
import sscce.mycode.b.RestrictedObject;
import sscce.usercode.SomeUserClass;
public class SomeClass {
public static void main(String[] args) {
SomeUserClass userClass=new SomeUserClass();
// If I can create it from here, anyone can...
RestrictedObject object=new RestrictedObject();
userClass.someMethod(object);
}
}
sscce.mycode.b.Interface.java:
package sscce.mycode.b;
public interface Interface {
public void someMethod(RestrictedObject restrictedObject);
}
sscce.mycode.b.RestrictedObject.java:
package sscce.mycode.b;
public class RestrictedObject {
public RestrictedObject() {}
}
sscce.usercode.SomeUserClass.java:
package sscce.usercode;
import sscce.mycode.b.Interface;
import sscce.mycode.b.RestrictedObject;
public class SomeUserClass implements Interface {
#Override
public void someMethod(RestrictedObject restrictedObject) {
// It receives an instance, but cannot create it.
System.out.println("Got "+restrictedObject);
}
}
Motivation: Having everything in one package sounds messy...
Does anyone have ideas on how to accomplish this without flattening the packages?
Thanks in advance for any solutions, ideas or comments, Till
You could do it the following way, however you should carefully consider if you really want to use this approach as it is very slow and quite frankly, bad practice.
I'll put it up anyway as to how you can do it:
public final class Secured {
private static final Set<Class<?>> allowedCallers = new HashSet<>();
static {
allowedCallers.add(Allowed.class);
}
private static final class SecurityManagerExtension extends SecurityManager {
private static final int OFFSET = 4;
#Override
protected Class<?>[] getClassContext() {
return super.getClassContext();
}
private Class<?> getCaller() {
try {
return getClassContext()[OFFSET];
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
}
}
private Secured() {
// protect against reflection attack
Class<?> caller = new SecurityManagerExtension().getCaller();
if (!this.getClass().equals(caller)) {
throw new IllegalStateException();
}
System.out.println("Secured instance constructed!");
}
public static Secured createInstance() {
// this gets the class name of the calling class
Class<?> caller = new SecurityManagerExtension().getCaller();
if (allowedCallers.contains(caller)) {
System.out.println("Created instance by '" + caller + "'!");
return new Secured();
} else {
System.out.println("No instance created because call was made by '" + caller + "'!");
return null;
}
}
}
Note the final keyword on the class to prevent subclassing. If you need to subclass the class yourself, move the final keyword to the factory method.
Also note that this is not protected against serialization attacks.

Override member data in subclass, use in superclass implementation?

In Java, is it possible to override member data in a subclass and have that overridden version be the data used in a super class's implementation?
In other words, here's what I am trying to get to happen, and it's not happening:
abstract public class BasicStuff {
protected String[] stuff = { "Pizza", "Shoes" };
public void readStuff() {
for(String p : stuff) {
system.out.println(p);
}
}
}
..
public class HardStuff extends BasicStuff {
protected String[] stuff = { "Harmonica", "Saxophone", "Particle Accelerator" };
}
This invocation:
HardStuff sf = new HardStuff();
sf.readStuff();
... prints Pizza and Shoes. I want it to print the latter instead.
I recognise that this is rather poor hierarchical OO practice; I needed it for a very specific case as I am doing something with XML configuration and reflection.
Is there a modifier that can make this happen?
And yes, I do recognise that there are wrappers one can use to get around this problem in my subclass, i.e. by indicating that the contents of stuff[] are now stored in an array with a different name, for instance. I'm just trying to keep this simple, and am curious in principle.
Thanks a lot in advance!
I believe you must interpose an accessor method, i.e., use:
for(String p : getStuff()) {
in the superclass, and add:
protected String[] getStuff() { return stuff; }
wherever you have a protected String[] stuff redefinition.
Overriding really applies to methods, not data (at least, that is so in the Java model; some other languages do things differently), and so to get the override effect you must interpose a method (typically a dirt-simple accessor, like here). It doesn't really complicate things at all, it's just a very simple way to instruct the Java compiler to use, intrinsically, the "extra level of indirection" that your desired behavior requires.
This way you are hiding the parent variable stuff with the defined stuff.
Try giving value to stuff in the initialization block (or in the constructor):
abstract public class BasicStuff {
protected String[] stuff;
{
stuff = new String[] { "Pizza", "Shoes" };
}
public void readStuff() {
for(String p : stuff) {
System.out.println(p);
}
}
}
..
public class HardStuff extends BasicStuff {
{
stuff = new String[] { "Harmonica", "Saxophone", "Particle Accelerator" };
}
}
If you want to print the array of the String Stuff defined in derived class then you need to override the method readStuff in the class HardStuff by redefining the method in the class HardStuff. As the method readStuff was defined in the abstract class BasicStuff, hence it would only print the members of the class BasicStuff. Hence, add the same method in the derieved class too.
Below you can find the complete code..
class BasicStuff {
protected String[] stuff = { "Pizza", "Shoes" };
public void readStuff() {
for(String p : stuff) {
System.out.println(p);
}
}
}
public class HardStuff extends BasicStuff {
protected String[] stuff =
{ "Harmonica",
"Saxophone",
"Particle Accelerator"
};
public void readStuff() {
for(String p : stuff) {
System.out.println(p);
}
}
public static void main(String []arg)
{
HardStuff sf = new HardStuff();
sf.readStuff();
}
}

Categories

Resources