So I've scoured the internet for a fix, and i've gotten tips to use maps, the reflect method, and a ton of other stuff, but nothing has worked the way I wanted.
My goal is to do something like this:
I have a string divided into an array. Example: "setVal strength 3"
lineArray[0] = setVal
lineArray[1] = strength
lineArray[2] = 3
I want to take lineArray[1] and add "Feats." to the beginning of it, so it it, for example, something like "Feats.strength" (which I can do with a string variable)
I then want to set that variable (Feats.strength, it's a double called strength in the Feats class) to lineArray[2] (which is a double).
else if(lineArray[0].equals("setVal") && lineArray.length == 2){
//Take lineArray[1], which is the name of a variable in
another class, specifically Feats.strength, Feats.agility, etc.
//Set that value in lineArray[1] to lineArray[2]
//Something like
set("Feats." + lineArray[1], lineArray[2]);
Feats.resetStat();
}
Does that make any sense? Thanks for the help in advance!
Maybe something like this would work?
// Application.java
public class Application {
public static void main(String[] args){
String field = "setVal strength 3";
Feats.resolveValue(field);
String field2 = "getVal strength";
Integer value = Feats.resolveValue(field2);
String field3 = "clearAll";
Feats.resolveValue(field3);
}
}
--
// Feats.java
public class Feats {
private static final Logger LOGGER = LoggerFactory.getLogger(Feats.class);
private static final Map<String, Integer> ATTRIBUTES = new HashMap<>();
public static String resolveString(String fieldInput){
String response = null;
String[] values = fieldInput.split(" ");
Action action;
try {
action = Action.valueOf(values[0].trim().toUppercase());
} catch(Exception e){
LOGGER.error("Not a valid Action in input: " + fieldInput);
return response;
}
switch(action){
case SETVALUE:
setValue(values[1].trim(), values[2].trim());
break;
case CLEARALL:
clearAll();
break;
case GETVALUE:
response = getValue(values[1].trim());
break;
default:
assert true;
}
return response;
}
private static void setValue(String attrName, String attrValue){
ATTRIBUTES.put(attrName, attrValue);
}
private static String getValue(String attrName){
return ATTRIBUTES.get(attrName);
}
private static void clearAll(){
ATTRIBUTES.clear();
}
}
--
// Action.java
public enum Action {
SETVALUE, CLEARALL, GETVALUE
}
So I solved it. Thanks to #shmosel for telling me to use a field.
long temp = Long.parseLong(lineArray[2]);
try {
Feats.class.getField(lineArray[1]).set(lineArray[1], temp);;
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e1) {
e1.printStackTrace();
}
Related
I am new at java . I have method witch contain some variables with different data type i.e. String and Array
pNumber=rs.getString("pNumber");
userName=rs.getString("userName");
simOperater=rs.getString("simOperater");
AdharNumber=rs.getString("AdharNumber");
rechargeAmount[i]=rs.getString("rechargeAmount");
activeDate[i]=rs.getString("activeDate");
plainDeatils[i]=rs.getString("plainDeatils");
and I want to return all the variables from single method in java so what approach should I use please help
just return a response object
public class MyResponse {
public String pNumber;
public String userName;
//....
}
usage:
public MyResponse yourMethod() {
MyResponse myResponse = new MyResponse();
myResponse.pNumber=rs.getString("pNumber");
myResponse.userName=rs.getString("userName");
//...
return myResponse;
}
If you don't want to write more lines, you can also set the return type of your method to Object and return your variable as you normally would, but then cast the returned object into the right type as it was before.
e.g.
class test {
static Object test_return(int which) {
String s = "This is a string";
int i = 100;
if(which == 0) {
return s;
} else {
return i;
}
}
public static void main(String args[]) {
String s = (String) test_return(0);
int i = (int) test_return(1);
System.out.println("String: " + s + "\nint: " + i);
}
}
output:
String: This is a string
int: 100
edit:
since you are new to java, you might not understand how types exactly work here. so I would suggest you read this and this to learn more about autoboxing and unboxing
So I have this class "Member" :
package pkgData;
import java.io.Serializable;
public class Member implements Comparable<Member>, Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
private String city;
public Member(String nameOfMember,String location) {
super();
this.name = nameOfMember;
this.city=location;
}
public String getNameOfMember() {
return name;
}
public String getLocationOfMember() {
return city;
}
public void setNameOfMember(String nameOfMember) {
this.name = nameOfMember;
}
#Override
public String toString() {
return name +", " + city;
}
#Override
public int compareTo(Member o) {
int result =this.getNameOfMember().compareTo(o.getNameOfMember());
if(result==0){
result = this.getLocationOfMember().compareTo(o.getLocationOfMember());
}
return result;
}
}
And I have a JComboBox which is EDITABLE and the model of the ComboBox is DefaultComboBoxModel.
So the problem is that if I cast the selectedItem:
Member nameOfMember = (Member)memberModel.getSelectedItem();
if(nameOfMember== null)
throw new Exception("please select a name and a location");
It only checks if the entered string is empty. If I enter a string like "Name, Location" I always get the exception that String cannot be cast to Member. Which String to I have to enter that the String can be cast to Member?
Here is my JComboBox:
private JComboBox<Member> getComboBoxMember() {
if (comboBoxMember == null) {
comboBoxMember = new JComboBox<Member>();
comboBoxMember.setEditable(true);
comboBoxMember.setModel(memberModel);
}
return comboBoxMember;
}
and here the global variables:
private DefaultComboBoxModel<Member> memberModel;
private JComboBox<Member> comboBoxMember;
String nameOfMember = (String) memberModel
.getSelectedItem();if(nameOfMember==null)throw new Exception("please select a name and a location");else
{
String[] parts = nameOfMember.split(",");
String part1 = parts[0]; // name
String part2 = parts[1]; // location
Member member=new Member(part1, part2);
}
String split & cast method
What you can do is first of all test if the string you get is null, or if it matches well you format. Then, you can create a new object with these elements.
Here's a small example code :
String memberData = (String)memberModel.getSelectedItem();
if(memberData == null || memberData.split(", ")[0].isEmpty() || memberData.split(", ")[1].isEmpty()) {
throw new Exception("Data is incorrect, please provide name and location separated with ", ");
}
Member member = new Member(memberData.split(", ")[0], memberData.split(", ")[1]);
JComboBox method
With Java 7 happened a new possibility of extension to JComboBox, which can now be generically parameterized (as for ArrayLists) in the form JComboBox<Type>. Thus, the objects you can get with getSelectedItem() can now be casted to the generic type you gave in parameter to JComboBox. The only problem is that, when a JComboBox is edited, as in your case, the data is casted to a simple String.
What you can do in your listener method (I will use ActionListener) is the following :
class ItemAction implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
try {
//In case the user has not modified the object
Member member = (Member)box.getSelectedItem();
//Just an example here
if(member != null) {
System.out.println(member.toString());
}
} catch(ClassCastException ex) {
//In case the object has been modified
String data = (String)box.getSelectedItem();
//Apply first method here
}
}
}
But the problem with this method is that you end up using the first method still.
I need to write the logic with many conditions(up to 30 conditions) in one set of rule with many if else conditions and it could end in between or after all the conditions.
Here is the sample code I have tried with some possible scenario. This gives me result but doesn't look good and any minor miss in one condition would take forever to track.
What I have tried so far is, Take out common conditions and refactored to some methods. Tried creating interface with conditions and various set would implement it.
If you have any suggestion to design this, would help me. Not looking for detailed solution but even a hint would be great.
private Boolean RunCondition(Input input) {
Boolean ret=false;
//First if
if(input.a.equals("v1")){
//Somelogic1();
//Second if
if(input.b.equals("v2"))
//Third if
if(input.c >1)
//Fourth if
//Somelogic2();
//Go fetch key Z1 from database and see if d matches.
if(input.d.equals("Z1"))
System.out.println("Passed 1");
// Fourth Else
else{
System.out.println("Failed at fourth");
}
//Third Else
else{
if(input.aa.equals("v2"))
System.out.println("Failed at third");
}
//Second Else
else{
if(input.bb.equals("v2"))
System.out.println("Failed at second");
}
}
//First Else
else{
if(input.cc.equals("v2"))
System.out.println("Failed aat first");
}
return ret;
}
public class Input {
String a;
String b;
int c;
String d;
String e;
String aa;
String bb;
String cc;
String dd;
String ee;
}
The flow is complicated because you have a normal flow, plus many possible exception flows when some of the values are exceptional (e.g. invalid).
This is a perfect candidate to be handled using a try/catch/finally block.
Your program can be rewritten into following:
private Boolean RunCondition(Input input) {
Boolean ret=false;
try {
//First if
if(!input.a.equals("v1")) {
throw new ValidationException("Failed aat first");
}
//Somelogic1();
//Second if
if(!input.b.equals("v2")) {
throw new ValidationException("Failed at second");
}
//Somelogic2()
//Third if
if(input.c<=1) {
throw new ValidationException("Failed at third");
}
//Fourth if
//Somelogic2();
//Go fetch key Z1 from database and see if d matches.
if(!input.d.equals("Z1")) {
throw new ValidationException("Failed at fourth");
}
System.out.println("Passed 1");
} catch (ValidationException e) {
System.out.println(e.getMessage());
}
return ret;
}
Where you can define your own ValidationException (like below), or you can reuse some of the existing standard exception such as RuntimeException
class ValidationException extends RuntimeException {
public ValidationException(String arg0) {
super(arg0);
// TODO Auto-generated constructor stub
}
/**
*
*/
private static final long serialVersionUID = 1L;
}
You can read more about this in
https://docs.oracle.com/javase/tutorial/essential/exceptions/index.html
Make a separate class for the condition:
package com.foo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class App
{
static class Condition<T> {
final int idx;
final T compareValue;
public Condition(final int idx, final T compareValue) {
this.idx = idx;
this.compareValue = compareValue;
}
boolean satisfies(final T other) {
return other.equals(compareValue);
}
int getIdx() {
return idx;
}
}
public static void main( String[] args )
{
final List<Condition<String>> conditions = new ArrayList<Condition<String>>();
conditions.add(new Condition<String>(1, "v1"));
conditions.add(new Condition<String>(2, "v2"));
final List<String> inputs = new ArrayList<String>(Arrays.asList("v1", "xyz"));
boolean ret = true;
for (int i = 0; i < inputs.size(); i++) {
if (!conditions.get(i).satisfies(inputs.get(i)))
{
System.out.println("failed at " + conditions.get(i).getIdx());
ret = false;
break;
}
}
System.out.println("ret=" + ret);
}
}
#leeyuiwah's answer has a clear structure of the conditional logic, but exceptions aren't the right tool for the job here.
You shouldn't use exceptions to cope with non-exceptional conditions. For one thing, exceptions are really expensive to construct, because you have to walk all the way up the call stack to construct the stack trace; but you don't need the stack trace at all.
Check out Effective Java 2nd Ed Item 57: "Use exceptions only for exceptional conditions" for a detailed discussion of why you shouldn't use exceptions like this.
A simpler option is to define a little helper method:
private static boolean printAndReturnFalse(String message) {
System.out.println(message);
return false;
}
Then:
if(!input.a.equals("v1")) {
return printAndReturnFalse("Failed aat first");
}
// etc.
which I think is a simpler; and it'll be a lot faster.
Think of each rule check as an object, or as a Strategy that returns whether or not the rule passes. Each check should implement the same IRuleCheck interface and return a RuleCheckResult, which indicates if the check passed or the reason for failure.
public interface IRuleCheck
{
public RuleCheckResult Check(Input input);
public String Name();
}
public class RuleCheckResult
{
private String _errorMessage;
public RuleCheckResult(){}//All Good
public RuleCheckResult(String errorMessage)
{
_errorMessage = errorMessage;
}
public string ErrorMessage()
{
return _errorMessage;
}
public Boolean Passed()
{
return _errorMessage == null || _errorMessage.isEmpty();
}
}
public class CheckOne implements IRuleCheck
{
public RuleCheckResult Check(Input input)
{
if (input.d.equals("Z1"))
{
return new RuleCheckResult();//passed
}
return new RuleCheckResult("d did not equal z1");
}
public String Name();
}
Then you can simply build a list of rules and loop through them,
and either jump out when one fails, or compile a list of failures.
for (IRuleCheck check : checkList)
{
System.out.println("checking: " + check.Name());
RuleCheckResult result = check.Check(input);
if(!result.Passed())
{
System.out.println("FAILED: " + check.Name()+ " - " + result.ErrorMessage());
//either jump out and return result or add it to failure list to return later.
}
}
And the advantage of using the interface is that the checks can be as complicated or simple as necessary, and you can create arbitrary lists for checking any combination of rules in any order.
I have a list of enums like the below -
List<Status> statusList;
Status is defined as below
enum Status { YES , NO , MAYBE }
The list contains
Status stat = Status.YES;
statusList.add(stat);
I have a variable
Status statusVar = Status.YES;
I am trying to a comparison like below but it is not working as I guess it is comparing the references. The below returns false. Can you please suggest a solution?
statusList.contains(statusVar)
EDIT: Below is the code that is not working. Status is string not Enum
import java.util.ArrayList;
import java.util.List;
public class Test {
private enum Status {
YES , NO , MAYBE
}
public static void main (String[] args){
List<Status> statusList = new ArrayList<Status>();
String status = "YES";
statusList.add(Status.YES);
if(statusList.contains(status)){
System.out.println(" Yes ");
} else {
System.out.println(" No ");
}
}
}
If you are performing a contains, it will be much more efficient if you use an EnumSet
Set<Status> status = EnumSet.of(Status.YES);
assert status.contains(Status.YES);
However, List<Status> will also work.
You are right it does compare the reference, but this will only fail if you have
multiple ClassLoaders and the Class Status is actually different.
you create new instances of the Status which you can do using Unsafe.allocateInstance(Status.class)
What is more likely is you are not testing what you think you are and the situation isn't exactly as you have described.
private enum Status {
YES , NO , MAYBE
;
public Status getByName(String name){
for (Status st : Status.values()) {
if (st.toString().equals(name)){
return st;
}
}
return null;
}
}
try this!
You could add a function toString() and contains() as helpers:
private enum Status {
YES("Yes") , NO ("Yes") , MAYBE("Yes");
private final String label;
/**
* Instantiates a new Status.
* #param label the label
*/
private Status (final String label) {
this.label = label;
}
#Override
public String toString() {
return label;
}
public static boolean contains(final String test) {
for (final Status value : Status.values()) {
if (value.toString().equals(test)) {
return true;
}
}
return false;
}
}
enum Status { YES , NO , MAYBE }
public static void main(String[] args) {
List<Status> lista = new ArrayList<>();
lista.add(Status.YES);
Status stat = Status.YES;
System.out.println(lista.contains(Status.YES));//true
System.out.println(lista.contains(stat));//true
}
I made this code and print both ways and it worked perfectly
or
you remembered to instantiate the variable statusList
In this program I have three numbers the user enters in and I am trying to get the second number in the set to display by being pulled from the DTO so that I can confirm that everything is working fine. But something is going wrong as you'll see by the output...
User Enters: 858508321,858509491,858510385
//This code is what is being executed. (Think of it as main)
private void handleSubmit(final AjaxRequestTarget target) {
List<Long> msgNums = new ArrayList<Long>();
msg_Num = Ta.getInput();
String[] Numbers = msg_Num.split(",");
for(String Number:Numbers){
msgNums.add(Long.valueOf(Number));
}
System.out.println(msgNums.get(1));
List<BulkReplayMessageDTO> brm = messageReplayDao.getMessageResults(msgNums);
System.out.println(brm.get(1).getMsgNum());
}
//This is the DAO
public class MessageReplayDao extends SimpleJdbcDaoSupport {
private final static String sql = "SELECT MSG_NBR, MSG_CPSD_DATA"
+ " FROM nti_raw_msg"
+ " WHERE THRD_NAME IS NOT null AND THRD_NAME NOT LIKE"
+ " 'out%' AND MSG_NBR IN (:messageNumbers)";
public List<BulkReplayMessageDTO> getMessageResults(final List<Long> msgNumList){
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("messageNumbers", msgNumList);
List<BulkReplayMessageDTO> result = getSimpleJdbcTemplate().query(sql, new MessageReplayMap(), parameters);
return result;
}
}
//The Map
public class MessageReplayMap implements ParameterizedRowMapper<BulkReplayMessageDTO> {
public MessageReplayMap(){
}
LobHandler lobHandler = new DefaultLobHandler();
#Override
public final BulkReplayMessageDTO mapRow(ResultSet rs, int rowNum)
throws SQLException {
final BulkReplayMessageDTO brm = new BulkReplayMessageDTO();
System.out.println(rowNum);
brm.setMsgNum(rs.getLong("MSG_NBR"));
brm.setMSG(CompressionUtils.uncompress(lobHandler.getBlobAsBytes(rs, "MSG_CPSD_DATA")));
return brm;
}
}
//And finally the DTO
public class BulkReplayMessageDTO{
private static Long msgNum;
private static String MSG;
public final Long getMsgNum() {
return msgNum;
}
public final void setMsgNum(final Long msgNumTemp) {
msgNum = msgNumTemp;
}
public final String getMSG(){
return MSG;
}
public final void setMSG(final String MSGTemp){
MSG = MSGTemp;
}
}
Notice that I have printed to the console in the handleSubmit method, and inside my map. The output I get is
858509491
0
1
2
858510385
when it should be
858509491
0
1
2
858509491
I have no clue what the problem could be since I have found other code example that are pretty much the same and mine seems to be pretty similar. I am pretty new to using Spring, so sorry if the answer is really obvious.
I have found the problem, and it was a really simple one. In the DTO the variables were made static from a previous problem I was working on. I had forgotten to get rid of it after I had fixed the issue. If I understand the meaning of static, then I had made all the instances of those variables the same. So that is why I could only print out the last number that had been entered in by the user.