Java Reflection getDeclaredMethod() with Class Types - java

I'm trying to understand Java reflecton and am encountering difficulties when working with non-Integer setter methods.
As an example, how can I resolve the "getDeclaredMethod()" call below?
import java.lang.reflect.*;
class Target {
String value;
public Target() { this.value = new String("."); }
public void setValue(String value) { this.value = value; }
public String getValue() { return this.value; }
}
class ReflectionTest {
public static void main(String args[]) {
try {
Class myTarget = Class.forName("Target");
Method myMethod;
myMethod = myTarget.getDeclaredMethod("getValue"); // Works!
System.out.println("Method Name: " + myMethod.toString());
Class params[] = new Class[1];
//params[0] = String.TYPE; // ?? What is the appropriate Class TYPE?
myMethod = myTarget.getDeclaredMethod("setValue", params); // ? Help ?
System.out.println("Method Name: " + myMethod.toString());
} catch (Exception e) {
System.out.println("ERROR");
}
}
}

params[0] = String.class;
Using class on String will return the Class<?> that is associated with the String class.

Related

Java. Factory creation should return Generic class

Could someone please help.
I would like to create a Factory, which would return specific class.
Having problem on the line - filterFactory.getFilter(myColumn.getType()).setMin(5);
There is an error: Cannot resolve method 'setMin' in 'Object'
public enum Columns {
Name(ColumnType.String),
Age(ColumnType.Numeric);
private final ColumnType type;
Columns(ColumnType type) {
this.type = type;
}
public ColumnType getType() {
return type;
}
}
public enum ColumnType {
String,
Numeric
}
public class NumericFilter extends ColumnFilter {
public void setMin(int min) {
System.out.println("min is set" + min);
}
}
public class StringFilter extends ColumnFilter {
public void setFilter(String filter) {
System.out.println("filter is set to:" + filter);
}
}
public class ColumnFilterFactory {
public <T> T getFilter(ColumnType type) {
if (type == null) {
return null;
}
if (type == ColumnType.String) {
return (T) new StringFilter();
} else if (type == ColumnType.Numeric) {
return (T) new NumericFilter();
}
return null;
}
}
public class BasicTest {
public static void main(String[] args) {
Columns myColumn = Columns.Age;
ColumnFilterFactory filterFactory = new ColumnFilterFactory();
filterFactory.getFilter(myColumn.getType()).setMin(5);
}
}
There's no way the compiler can know what type the factory is going to return, so you need to give it a little help. For example by using an intermediate variable:
NumericFilter nf = filterFactory.getFilter(myColumn.getType());
nf.setMin(5);

in java multi-catch every multi-catch character is final, but I'm not able to get it

class Main
{
public static void main(String args[])
{
try{
throw new ArrayIndexOutOfBoundsException("yyyoyo");
}
catch(ArrayIndexOutOfBoundsException |ArithmeticException e)
{
e.initCause(new Exception());
}
}
}
As we know that multi-catch parameter is implicitly final, so how I'm able to chain an exception in the catch block.
A final reference means you can not assign a new value to it. It does not stop the object from being updated.
For example:
class MyClass {
String string;
public MyClass(String string) {
super();
this.string = string;
}
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
#Override
public String toString() {
return "MyClass [string=" + string + "]";
}
}
public class Main {
public static void main(String[] args) {
final MyClass obj = new MyClass("Test");
System.out.println(obj);
obj.setString("Testing");
System.out.println(obj);
// obj= new MyClass("Testing"); // Trying to assign a new value to obj will result in a compilation error
}
}
Output:
MyClass [string=Test]
MyClass [string=Testing]

Pass object of any type to class B

I want to be able to pass Object from any class to a specific class. How do i do this? I pass the object in the constructor of the receiving class. One workaround i know is using static variables, but i need the whole object not just the variables.
public class tryitout
{
public static void main(String[] args) {
A a = new A();
B b = new B(a);
b.print();
}
}
class A implements Serializable
{
public int a;
public String b;
A()
{
this.a = 12;
this.b =" nach";
}
}
class B
{
Object obj;
B(Object o)
{
obj = o;
}
void print()
{
System.out.println(obj.a + " "+ obj.b);
}
}
Using Generics :
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class tryitout {
public static void main(String[] args) {
ClassA a = new ClassA("sap",11);
ClassB<ClassA> b = new ClassB<ClassA>(a);
b.print();
}
}
public class ClassA {
private String name;
private int id;
public ClassA(String name, int id) {
super();
this.name = name;
this.id = id;
}
#Override
public String toString() {
return "ClassA [name=" + name + ", id=" + id + "]";
}
}
public class ClassB<T> {
private T genericObj;
public ClassB(T genericObj){
this.genericObj = genericObj;
}
public void print() {
Field nameField = getField("name");
Field idField = getField("id");
try {
System.out.println(nameField.get(genericObj));
System.out.println(idField.getInt(genericObj));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private Field getField(String FieldName) {
Field fld = null;
try {
fld = genericObj.getClass().getDeclaredField(FieldName);
if(Modifier.isPrivate(fld.getModifiers())) {
fld.setAccessible(true);//To get access over private fields
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return fld;
}
}
using generics you can access method also.
I don't know your exact purpose,otherwise other classes can extend any particular Abstract class and you can use that Abstract class as a type inside classB.
public class TypeClass {
protected String name;
protected int id;
protected void paint(){
System.out.println("name: " + name + " | id: " + id);
}
}
public class ClassC extends TypeClass{
public ClassC(String name, int id) {
super();
this.name = name;
this.id = id;
}
#Override
public String toString() {
return "ClassA [name=" + name + ", id=" + id + "]";
}
}
package javaConcept.generics;
public class ClassD {
private TypeClass typeClass;
public ClassD(TypeClass typeClass) {
this.typeClass = typeClass;
}
public void newPaint() {
typeClass.paint();
}
}
public class TempoClass {
public static void main(String[] args) {
ClassC c = new ClassC("sap",11);
ClassD b = new ClassD(c);
b.newPaint();
}
}
maybe use static blocks and anonymous blocks some thing like this
public class HelloWorld{
public static void main(String []args){
B ob1= new B();
C ob2= new C(B.ob);
D ob3= new D();
C ob4= new C(ob3.ob);
}
}
class A
{
//this is empty class just for sake of object to be created
public void imWorking()
{
System.out.println("test");
}
}
class B
{
public static A ob;
static{ob=new A();}//static called once class gets loaded
}
class C
{
public C(){}//Default constructor
public C(A a){a.imWorking();}
}
class D
{
public A ob;
{ob=new A();}//ananomous block calls everytime a new object is created
}
more info Static Initialization Blocks blocks & anonymous blocks][1]

Modify property of non-null field using relection/annotations

I have this:
package general;
import org.junit.Test;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
#Retention(RetentionPolicy.RUNTIME)
#interface SetTable {
String table();
}
class Star {
public String foo = "";
public String toString(){
return "<Star> : " + this.foo;
}
}
class Bar {
#SetTable(table = "xxx")
public Star s = new Star();
public String toString(){
return "<Bar> : " + this.s.toString();
}
}
class AnnotationInjector {
public static void inject(Object instance) {
Field[] fields = instance.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(SetTable.class)) {
SetTable set = field.getAnnotation(SetTable.class);
field.setAccessible(true); // should work on private fields
try {
field.set(instance, set.table()); // this is not what I need
// ***
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public class AnnotationTest {
#Test
public void first() {
var b = new Bar();
AnnotationInjector.inject(b);
System.out.println(b.toString());
}
}
right now the code is trying to set new Bar().s to a String, but that won't work, because new Bar().s needs to be an instance Star. But that's not what I want to do anyway. What I want to do is access s and set this:
new Bar().s.foo = "whatever"
so on the line above designated by ***
I am looking to do something like:
((Star)field).foo = "whatever";
but that's not right. Is it possible to modify a field after it's been assigned?
Counterintutively, the syntax to do this is:
Star x = (Star)field.get(instance);
this line can modify the properties of the pre-existing Star s field on Bar.
As an alternative I suggest you add an interface with method for setting the value in order to make setting the value more general instead of checking on instances and their types, and make the Star class implements it, as the following:
interface ISetValue {
void setValue(String value);
}
class Star implements ISetValue{
public String foo = "";
#Override
public void setValue(String value) {
foo = value;
}
public String toString(){
return "<Star> : " + this.foo;
}
}
And your AnnotationInjector class should check if the field implements ISetValue and onvoke setValue method for it, should be something like the following:
class AnnotationInjector {
public static void inject(Object instance) {
Field[] fields = instance.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(SetTable.class)) {
SetTable set = field.getAnnotation(SetTable.class);
field.setAccessible(true); // should work on private fields
try {
//field.set(instance, set.table()); // this is not what I need
// ***
//Change is here
Class fieldType = field.getType();
if(ISetValue.class.isAssignableFrom(fieldType) ){
Object fieldValue = field.get(instance);
Method myMethod = fieldValue.getClass().getInterfaces()[0].getDeclaredMethod("setValue", new Class[]{String.class});
myMethod.invoke(fieldValue,set.table());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
Now your output should be:
<Bar> : <Star> : xxx

Why is Paranamer not returning the method names when using CachingParanamer?

I'm trying to use the paranamer library to retrieve the parameter names of my classes.
However, it does not return the parameter name of one method. Here's the class with the method with parameter that I'm trying to return the name:
package domain;
public class DomainTest {
private String attribute1;
private int attribute2;
public DomainTest() {
}
public DomainTest(String attribute1, int attribute2) {
super();
this.attribute1 = attribute1;
this.attribute2 = attribute2;
}
public void someMethod(String paramTest) {
System.out.println("METHOD IN DOMAIN CLASS");
}
public String getAttribute1() {
return attribute1;
}
public int getAttribute2() {
return attribute2;
}
}
The method someMethod.
And here the class trying to return the parameters' names:
package tests;
import java.lang.reflect.Method;
import com.thoughtworks.paranamer.CachingParanamer;
import com.thoughtworks.paranamer.Paranamer;
import domain.DomainTest;
public class Test {
public static void main(String[] args) {
Class<?> myClass = DomainTest.class;
System.out.println("CLASS NAME " + myClass.getCanonicalName());
String[] ParameterNames = null;
Paranamer paranamer = new CachingParanamer();
for (Method method : myClass.getDeclaredMethods()) {
System.out.println("METHOD NAME: " + method.getName());
ParameterNames = paranamer.lookupParameterNames(method, false);
if (ParameterNames.length > 0) {
System.out.println("OK!");
} else {
System.out.println("NO!");
}
}
System.out.println("TESTING!");
for (int i = 0; i < ParameterNames.length; i++) {
System.out.println("PARAMETER NAME " + ParameterNames[i]);
}
}
}
I've also seen here that the paranamer class just can get the paramater names with the debug information set using -g in javac or setting it in the Java compiler in the Eclipse IDE.
I've done this, and it still did not work, not returning the parameter name of the method someMethod above. I'm using Paranamer 2.5.2.
How can I get Paranamer to return my method names in this scenario?
I've solved after a help in a brazilian forum (http://www.guj.com.br)
I have to use the AdaptiveParameter instead CachingParameter, this way:
Paranamer paranamer = new AdaptiveParanamer();

Categories

Resources