views:

143

answers:

5

two class:

public class BaseDo<K> {
    protected K id;

    public K getId() {
        return id;
    }

    public void setId(K id) {
        this.id = id;
    }
}


public class BeanDo extends BaseDo<Integer> {
    private String beanName;

    public String getBeanName() {
        return beanName;
    }

    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }
}

I want use reflect to implment like this:

BeanDo beanDo = new BeanDo();
beanDo.setId("string here");

Integer type reference String type value. who can help me?

A: 

Something like this?

public class BaseDo<K> {

  protected K id;

  public K getId() {
    return id;
  }

  public void setId(K id) {
    this.id = id;
  }

}

public class BeanDo extends BaseDo<Integer> { 

  private String beanName;

  public void setId(String id) {
    setId(Integer.parseInt(id));
  }

  public String getBeanName() {
    return beanName;
  }

  public void setBeanName(String beanName) {
    this.beanName = beanName;
  }

}

Now you can use something like this:

BeanDo beanDo = new BeanDo();
beanDo.setId("2");
rmarimon
-1 try it with: `beanDo.setId("string here");` Using `someString.hashCode()` is all that is needed, see my answer.
OscarRyz
@rmarimon At least leave me a comment about your downvote.
OscarRyz
A: 

What about this:

BeanDo beando = new BeanDo();
beando.setId("string there".hashCode());

I don't quite get what you mean with "I want to use reflect to implement this" though.

I guess you want something like this:

    BeanDo doer = ... // get it from somewhere
    String id   = ... // get it from somewhere else too. 

    // and you want to set id to the doer bean.
    reflectionMagicSetId( doer, id ); 

And have the method like:

 private void reflectionMagicSetId( BandDo doer, String id ) {
       /// do some magic here? 
 }

If that's what you want, what I give you works perfectly.

 private void reflectionMagicSetId( BandDo doer, String id ) {
     doer.setId( id == null ? 0 : id.hashCode()  );
 }
OscarRyz
It doesn't seem right to use String.hashCode() because multiple strings can produce the same hash value. That wouldn't work if it were used as a primary key in a database, for example.Maybe tidus2005 wants to make a compound key with an integer and a string? Impossible to know from the question.
Joshua Davis
Good point I guess the only resource remaining would be to subclass
OscarRyz
A: 

If you wann use integer then parse the string to integer as it will contain the integer and use that integer in the calling function argument

+1  A: 

Generics in Java are not used at runtime, so as far as the java runtime is concerned you're ID field is of type Object and so can be set to any value regardless of the generics. That said, doing so is a bad idea since anything assuming the generic contract will fail.

You can set the field by reflection as follows:

BeanDo beanDo = new BeanDo();
Method method = BeanDo.getClass().getMethod("setId", Object.class);
method.invoke(beanDo, "SomeRandomString");

That said, doing this is an extreamly bad idea because any code compile against BeanDo will assume that the id is an integer not a String. So any code like beanDo.getId() will fail with a class cast exception because it's not actually an integer.

Like the other posters, I'm somewhat in the dark about what you're trying to achieve.

EdC
I agree with this - just because you CAN doesn't mean you SHOULD. If you don't have access to every place getId() is called, you can't guarantee that you're not setting yourself up for problems later. If you DO have access to all the uses, you should just change the object to use a String explicitly.
Curtis
A: 

It seems like a subclass about the only way to be able to set a string, but still guarantee that anyone who's already calling getId() gets the Integer they expect. Something like this:

public class StringBeanDo extends BeanDo {
  private String stringId;

  public String getStringId()
  {
    return stringId;
  }

  public void setId( Integer val )
  {
    super.setId( val );
    stringId = Integer.toString( val );
  }

  public void setId( String str )
  {
    stringId = str;
    super.setId( convertStringToInteger( str )); // Do this however you like.
  }
}

The implementation of convertStringToInteger would be up to you (it'll depend on what this ID is being used for). The key here is that you're maintaining TWO IDs, and keeping them in sync, so that older code can still limp along to some extent.

Curtis