How to extract fields value from Object in Java - java

Here is Demo class
public class Demo {
int i;
String s;
}
I have an instance of Demo:
Demo demo = new Demo(1, "hello");
How can I get demo field values as array of Object like:
Object[] {1, "hello"};
Updated:
For new Object[] {demo.i, demo.s} I need know fields from Demo, however I need a general way to get Object array for any class that has primitive fields and/or simple fields.

you will need to make it yourself indeed. To get it how you showed, you will want a getter method in your object
public class Demo(){
int i;
String s;
public Demo(){
//constructor
}
public Object[] getDemo{
return new Object[] {i, s};
}
}

As stated in the comments, you can do it via reflection quite easily:
public static Object[] getFieldValues(Object o) {
return Arrays.stream(o.getClass().getDeclaredFields())
.map(field -> {
try {
return field.get(o);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
})
.toArray();
}
public static void main(String[] args) {
class Demo {
int i;
String s;
}
Demo d = new Demo();
d.i = 1;
d.s = "hello";
Object[] fieldValues = getFieldValues(d);
System.out.println(Arrays.toString(fieldValues));
}
However, also as stated in the comments, this might be an "X-Y problem" and there may be better solutions to what you are actually looking to achieve.

Related

java get collection of methods

I have some helper classes for testing with the following structure:
public class EntitiesForTest {
public static Entity firstEntity() {
return new Entity(/*some dummy data*/)
}
public static Entity secondEntity() {...}
...
public static Entity nthEntity() {...}
public static List<Entity> allEntities() {???}
}
The purpose of this classes is to have some objects to test the upper layers of my system, like having some JSON data to test a REST service. This technique is not mine but from an online course I'm taking and is pretty cool.
I'd like to know if there is a way to construct a List<Entity> based on the static inherited methods of the class and with the Collection framework. I can do Arrays.asList(/*call the methods one by one comma-separated*/) but there must be a smarter, functional and reusable way of doing this.
Thanks in advance for your answers.
"Modern" Way
public static List<Entity> getEntities() {
return Arrays.stream(Foo.class.getMethods()).
filter(method -> method.getReturnType() == Entity.class &&
Modifier.isStatic(method.getModifiers())).
map(method -> {
try {
return (Entity)method.invoke(null);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e); // exceptions in streams... lol
}
}).
collect(Collectors.toList());
}
I wish I knew a way to avoid the cast, but that's not immediately clear to me.
Here is the samele code for invoking specified methods of EntitiesForTest class and collect the return objects:
public static List<Entity> allEntities() {
ArrayList<Entity> list = new ArrayList<Entity>();
Method[] ma = EntitiesForTest.class.getMethods();
Object[] emptyObject = new Object[0];
for (int i = 0; i < ma.length; i++) {
if (ma[i].getReturnType().equals(Entity.class) &&
ma[i].getParameterTypes().length == 0 &&
Modifier.isStatic(ma[i].getModifiers())) {
try {
Entity e = (Entity)(ma[i].invoke(null, emptyObject));
list.add(e);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return list;
}
This answer makes several assumptions:
You don't need the individual methods (firstEntity, secondEntity, etc.)
The entities only hold data and are not expensive to create and keep around
You don't need to modify them, which means you wouldn't call your methods multiple times.
These might not hold, because we have no definition of Entity or how it's used.
All in all, I'm just removing your methods.
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class EntitiesForTest {
private static final List<Entity> entities = Arrays.asList(
new Entity(),
new Entity(),
new Entity()
);
public static Entity allEntities(int n) {
return entities.get(n);
}
public static List<Entity> allEntities() {
return Collections.unmodifiableList(entities);
}
}
Maybe using a functional way (in java 8 ) ?
public class Entities {
static class Entity{
private String x;
Entity( String x){
this.x = x;
}
public String getX(){
return x;
}
}
public static Entity firstEntity() {
return new Entity("first Entity");
}
public static Entity secondEntity() {
return new Entity("second Entity");
}
public static Entity nthEntity() {
return new Entity("nth Entity");}
#FunctionalInterface interface GetEntity{
public Entity getEntity();
}
public static List<GetEntity> allEntities =
Arrays.asList(Entities::firstEntity,
Entities::secondEntity,
Entities::nthEntity);
public static void main(String ...p){
allEntities
.stream()
.forEach(x->{System.out.println(x.getEntity().getX());});
}
}

Generic Singleton Factory

While reading online, I came across the following:
public interface UnaryFunction<T>
{
T apply(T arg);
}
.......
private static UnaryFuntion<Object> ID_FUNC = new UnaryFunction<Object>
{
Object apply(Object arg)
{
return arg;
}
};
public static <T> UnaryFunction<T> idFunction()
{
return (UnaryFunction<T>) ID_FUNC;
}
In main:
public static void main(String[] args)
{
String[] strings = {"Peter", "Paul", "Mary"};
UnaryFunction<String> names = idFunction();
for(String s : strings)
{
System.out.println(names.apply(s));
}
Number[] numbers = {1, 2.0, 3L};
UnaryFunction<Number> nums = idFunction();
for(Number n : numbers)
{
System.out.println(nums.apply(n));
}
}
My question is, why do we need a generic interface here?
Would simply the following suffice:
public interface UnaryFunction
{
Object apply(Object arg); //Object as return type and argument type, instead.
}
? What is the need here to use generics?
And, what is actually a generic singleton factory? What is it good for?
Thanks.
The generic singleton factory is the idFunction in your example. Without it you would have a choice between two ugly alternatives, either require a cast wherever you use it, like this:
public class ExampleWithoutGenericSingletonFactory {
static UnaryFunction<Object> ID_FUNC = new UnaryFunction<Object>() {
public Object apply(Object arg) {
return arg;
}
};
public static void main(String[] args) {
BigDecimal b = new BigDecimal("1234.1241234");
BigDecimal b1 = (BigDecimal)(ID_FUNC.apply(b)); // have to cast here >_<
System.out.println("engineeringstring val of b1 = "
+ b1.toEngineeringString());
}
}
or make separate implementations for every type you want to support:
public static UnaryFunction<String> ID_FUNC_STRING = new UnaryFunction<String>() {
public String apply(String arg) {
return arg;
}
};
public static UnaryFunction<Number> ID_FUNC_NUM = new UnaryFunction<Number>() {
public Number apply(Number arg) {
return arg;
}
};
public static UnaryFunction<BigDecimal> ID_FUNC_DECIMAL = new UnaryFunction<BigDecimal>() {
public Number apply(BigDecimal arg) {
return arg;
}
};
giving you some ugly verbose cut-n-pasted code with a different name for every type that you have to keep straight. But since you know it's a pure function and the types get erased, you can have only one implementation (ID_FUNC) and have the singleton factory idFunction return it.
You would use this for cases where you have one function implementation that you want to be able to specify different types on, where the implementation is stateless.
The example could be better, since it only calls toString on the objects returned from the function call there's no demonstrated benefit from the factory. If the example showed using type-specific methods on the objects returned then the benefit might be more apparent.
An unchecked cast warning comes up when you do this, but it's safe to suppress it (which is what Joshua Bloch advises).

Programmatically retrive parameters and values of a method

it's been quite a few months that i quite Java in favor of Python. Now i'm go back to java to project constraints.
now, i'm wondering if there's a way to get all the aprameters (with values) of a functions programmatically inside the function itself.
something like this
public void foo(String arg1,String arg2, Integer arg3){
... pars = ...getpars();
}
foo("abc","dfg",123);
where getpars() should return an HashMap with name,value pairs.
so from the example should be
arg1,"abc"
arg2,"dfg"
arg3,123
is there anything like this?
Unfortunately this is impossible. The only thing you can do is to retrieve the list of parameters types of a particular method using reflection.
But there is no way to get a map with name -> value of each argument passed into the method itself.
You can't get the name of the parameter, because it's no value just a name. If you wanna have the name of the parameter in your Map define a String which matches your parameter name and put it in.
Read this similar question. The accepted answer seems to have a solution for this using a third party library.
You can't get the names of the parameters dynamically, nor can you find the values in any way other than using the variable names. However, JAVA has the next best thing: variable arguments. If you want to have a dynamic number of arguments, you can declare your method as follows:
public void foo(Object... args)
When you call the method, you will call it with any number of arguments; foo(1, 2, "ABC") and foo(new File("config.dat"), new Scanner(), 88.5D) are both valid calls. Inside the function, args will be an array containing all of the parameters in order.
Just a few usage tips, though. The method declaration above is, in general, not considered good form. Usually, you can be much more specific. Think hard about whether or not you need all this flexibility, and consider using a few overloaded methods or possibly passing a HashMap to the function instead. Very rarely will you actually need to have dynamic parameters in that broad of a sense.
You could use:
void foo(String... args) {
for (String arg: args) { }
for (int i = 0; i < args.length - 1; i += 2) {
map.put(args[i], args[i + 1];
}
}
foo("a", "1", "b", "2");
Or use a Map builder, see builder-for-hashmap.
There are some hacky ways of getting the parameters values of an invoked method (But you have to understand that the parameters are unnamed, the best you can do is to get arg0.... argN).
Use Proxies
Aspect oriented programming (AspectJ, Spring AOP)
Let's consider the 1st approach. Say we want to log parameters before executing the method of some interface MethodParamsInterface, here you go. If you want to use these arguments in your logic - consider to implement them in InvocationHandler (or use EasyMock instead)
interface MethodParamsInterface {
void simpleMethod(int parm1, int parm2);
void simpleMethod(int parm1, int parm2, int param3);
}
public class MethodParams implements MethodParamsInterface {
public void simpleMethod(int parm1, int parm2) {
//business logic to be put there
}
public void simpleMethod(int parm1, int parm2, int param3) {
//business logic to be put there
}
public MethodParamsInterface wrappedInstance() throws Exception {
Class<?> proxyClass = Proxy.getProxyClass(MethodParams.class.getClassLoader(), MethodParamsInterface.class);
InvocationHandler invocationHandler = new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Map<String, Object> params = new LinkedHashMap<String, Object>(args.length);
for (int i = 0; i < args.length; i++)
params.put("arg" + i, args[i]);
//printing out the parameters:
for (Map.Entry<String, Object> paramValue : params.entrySet()) {
System.out.println(paramValue.getKey() + " : " + paramValue.getValue());
}
return MethodParams.this.getClass().getMethod(method.getName(), method.getParameterTypes()).invoke(MethodParams.this, args);
}
};
return (MethodParamsInterface) proxyClass.getConstructor(new Class[]{InvocationHandler.class}).newInstance(invocationHandler);
}
public static void main(String[] args) throws Exception {
MethodParams instance = new MethodParams();
MethodParamsInterface wrapped = instance.wrappedInstance();
System.out.println("First method call: ");
wrapped.simpleMethod(10, 20);
System.out.println("Another method call: ");
wrapped.simpleMethod(10, 20, 30);
}
}
import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
class Test01 {
public int method01(int i, int j) {
System.out.println("Original method01");
return i + j;
}
}
class ParameterWriter {
public static <T> T getObject(T inp) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(inp.getClass());
factory.setFilter(
new MethodFilter() {
#Override
public boolean isHandled(Method method) {
return true;
}
}
);
MethodHandler handler = new MethodHandler() {
#Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
for (int i = 0; i < args.length; i++) {
System.out.println(proceed.getParameters()[i].getName() + ":" + args[i]);
}
return proceed.invoke(self, args);
}
};
return (T) factory.create(new Class<?>[0], new Object[0], handler);
}
}
public class Main {
public static void main(String[] args) {
try {
Test01 test01 = ParameterWriter.getObject(new Test01());
test01.method01(2, 3);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
output:
arg0:2
arg1:3
Original method01

How do I use getConstructor(params).newInstance(args)?

This could well be a stupid question, but I'm new to Java, so...
I've currently got some code where currently this is being used
clazz.asSubclass(asSubclassOfClass).getConstructor().newInstance()
I need to pass some arguments to the contructort so I want to change it to: clazz.asSubclass(asSubclassOfClass).getConstructor(params).newInstance(args)
What I don't understand is what I need to pass in as params and what I need to pass in as args.
Let's say I wanted to pass in a String "howdy" and some object of type XYZ called XyzObj in. How would I specify that? WHat would I pass as params and what would I pass as args?
In Java this is called Reflection.
Assuming the class has this constructor, otherwise you will get a NoSuchMethod exception I believe.
clazz.asSubclass(asSubclassOfClass)
.getConstructor(String.class,XYZ.class)
.newInstance("howdy",XyzObj);
Since you are new to Java, let me give you an easier so that you can understand what's going on under the hood when you do this.
Assume you have the following class:
public class ParentClazz{
String someVar;
public ParentClazz(){
someVar="test";
}
public ParentClazz(String someVar){
System.out.println("I have been invoked");
this.someVar=someVar;
}
}
Then you have the following main method:
public static void main(String[] args) throws ParseException, IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
ParentClazz.class.asSubclass(ParentClazz.class).getConstructor(String.class).newInstance("howdy");
}
If you run this you will notice the console output print message - I have been invoked. This means that using reflection you have invoked the constructor of ParentClazz.
You can do the same thing if the scenario allows you is by using standard object creation process:
ParentClazz clazz = new ParentClazz("howdy");
Hope this helps you understand it.
Here is an example of creating classes without the new keyword.
The classes take other classes both primitives and Objects as their parameters.
The example also shows the instance of a subclass and a Parent class being created
public class ConstructorInstantiateWithoutNew
{
#SuppressWarnings("rawtypes")
public static void main( String [] args )
{
Class<Drinker> clazz_drinker = Drinker.class;
Class [] paramTypes = { Fizz.class, Colour.class, int.class };
Object [] paramValues = { new Fizz(), new Colour(), new Integer(10) };
Class<Drunk> clazz_drunk = Drunk.class;
Class [] paramTypesSub = { Fizz.class, Colour.class, int.class, boolean.class };
Object [] paramValuesSub = { new Fizz(), new Colour(), new Integer(10), true };
try
{
Drinker drinker = clazz_drinker.getConstructor( paramTypes ).newInstance( paramValues );
drinker.drink();
Drunk drunk = clazz_drunk.getConstructor(paramTypesSub).newInstance(paramValuesSub);
drunk.drink();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
class Drinker
{
int n;
public Drinker( Fizz f, Colour c, int n)
{
this.n = n;
}
public void drink()
{
System.out.println( "Dad drank " + (n*10) + " ml");
}
}
class Drunk extends Drinker
{
boolean trouble;
public Drunk(Fizz f, Colour c, int n, boolean inDogHouse)
{
super(f,c,n);
trouble = inDogHouse;
}
public void drink()
{
System.out.println(
"Dad is Grounded: " + trouble +
" as he drank over "+
(n*10) + " ml");
}
}
class Fizz {} class Colour {}
Hope this is useful
Kind regards
Naresh Maharaj
clazz.asSubclass(asSubclassOfClass)
.getConstructor(String.class, XYZ.class)
.newInstance("howdy", XyzObj)
Which assumes that the constructor args are in the specified order

Java constructor varargs conflict when passing string

I have an issue with one of my class. I'm using a "varargs" constructor for unknown number of parameter.
public Groupe(String...nom){
for(String item:nom){
this.nom.add(item.toLowerCase());
}
}
public Groupe(String nom){
String[] list =nom.split(",");
for(String s : list){
this.nom.add(s.toLowerCase());
}
}
The first constructor is called...that's fine, but there is a conflict when passing only ONE parameter with the second contructor. I would like to use the second constructor when passing only one string, and the first if 2 and more parameters.
I'd want to handle this
new Groupe("Foo,Bar");
This is where I call it. I suspect the "error" comes from there
public void reserver(String...nom){
Groupe gr = new Groupe(nom);
passager.add(gr);
}
I don't pass a String, but a Varargs (tab?)...
It should be fine, with the caveat that null can be converted to either String[] or String:
public class Test {
public Test(String single) {
System.out.println("Single");
}
public Test(String... multiple) {
System.out.println("Multiple");
}
public static void main(String[] args) {
new Test("Foo"); // Single
new Test("Foo", "Bar"); // Multiple
new Test(); // Effectively multiple
// new Test(null); // Doesn't compile - ambiguous
new Test((String) null); // Single
}
}
EDIT: Now that you've shown us the calling code, that's definitely the problem:
public void reserver(String...nom){
Groupe gr = new Groupe(nom);
passager.add(gr);
}
Here, the type of nom is String[] - so it will always call the first constructor. You've got an array of strings there - under what circumstances do you want to call the second constructor?
To be honest, given that the two constructors act significantly differently, I would actually make both constructors private, and provide static methods:
public static Groupe fromStringArray(String... nom)
public static Groupe fromCommaSeparatedString(String nom)
Then it will be absolutely clear what you're expecting in each case.
Maybe this can be a solution:
public Groupe(String...nom){
if (nom.length == 1) {
add(nom[0].split(","));
} else {
add(nom);
}
}
private void add(String[] list) {
for(String s : list){
this.nom.add(s.toLowerCase());
}
}
The varargs part can be empty. So you can get what you want with
public Groupe(String nom){
String[] list = nom.split(",");
for(String s : list){
this.nom.add(s.toLowerCase());
}
public Groupe(String nom1, String nom2, String...nom){
this.nom.add(nom1);
this.nom.add(nom2);
for(String item:nom)
this.nom.add(item.toLowerCase());
}
You could also, of course, use one ctor with an if statement on the length of the input array, splitting out cases 0 (not handled with the code above), 1, and > 1.
public class OverloadVarArgs {
public static void main(String... args){
OverloadVarArgs a = new OverloadVarArgs("One Argument");
OverloadVarArgs b = new OverloadVarArgs("Two", "Arguments");
OverloadVarArgs c = new OverloadVarArgs("One, Argument");
}
public OverloadVarArgs(String a){
System.out.println("Constructor 1");
}
public OverloadVarArgs(String... a){
System.out.println("Constructor 2");
}
}
Output:
Constructor 1
Constructor 2
Constructor 1

Categories

Resources