I have a Java program that communicates to a C program. I have written JNI before but my output structure was more simplistic and the C structure just contained doubles/ints and arrays of doubles/ints.
Now my structure contains a substructure (class/subclass) and I don't know how to change the code to access the subclass data/fields.
My C code looked like this but how do I access a value like DefaultFeeAmount if you look at my Java Class below this code....how do I get to the elements within the subclass?
C straightforward....
{
jclass out_rec_cls = jenv->GetObjectClass(ptrTo_out_rec);
jfieldID fldID, fldID2;
jintArray arr;
jdoubleArray darr;
jobjectArray oarr;
jsize len;//,len2;
jint *arrElems;
jdouble *darrElems;
jobject *oarrElems;
int i;
char temp_str[100],temp_str2[10000];
fldID = jenv->GetFieldID(out_rec_cls, "ErrorCode", "I");
if(fldID != NULL)
jenv->SetIntField(ptrTo_out_rec, fldID, out_rec->error_code);
}
Java
class FeeOutput {
public double DefaultFeeAmount;
public double MaximumAmount;
public int FeeID;
public int CompType;
public int Handling;
public int CapType;
public int ProfitType;
public int EffectiveDateMonth;
public int EffectiveDateDay;
public int EffectiveDateYear;
public int VendorBasedFee;
public int DealerRequestedFee;
public int DealerFixedTranFee;
public double FeeAmount;
public int FeeCompliant;
public String FeeName = "";
public FeeOutput() {
}
}
public class VFeeOutput {
public static final int NUM_FEES = 100;
public FeeOutput[] FeeStruct = new FeeOutput[NUM_FEES];
public int ErrorCode;
public String ErrorString = "";
public String Version = "";
public VFeeOutput() {
}
}
As a wide-spread Java convention tip, please start variable names with lower case. Here how you can access "struct" fields in Java.
public class VFeeOutput {
public static final int NUM_FEES = 100;
public FeeOutput[] FeeStruct = new FeeOutput[NUM_FEES];
public int ErrorCode;
public String ErrorString = "";
public String Version = "";
public VFeeOutput() {
}
private void loopThoughtFeeOutput() {
for(FeeOutput feeOutput : FeeStruct) {
feeOutput.CompType = ...;
}
// or
for(int i = 0; i < FeeStruct.length; i++) {
FeeStruct[0].CompType = ...;
}
}
}
Related
I have this code
public void insertStart_auto_load_test_step_info(int countUsers ) throws SQLException{
String insert_auto_load_test_user_info = "insert into auto_load_test_step_info(id_user_info,start_time,step_id) values(" + getIdValue1()+ getCrokStarTime() + "2";
PreparedStatement pstmt = this.con.prepareStatement(insert_auto_load_test_user_info, Statement.RETURN_GENERATED_KEYS);
pstmt.executeUpdate();
And this Class
public class Info {
private int crok = 0;
private int testId = 0;
private int testCaseId = 1;
private long starTime;
private long crokStarTime;
private long crokFinishTime;
int [] idValue1 = new int[100];
int [] idValue2 = new int[100];
int id_case_info = 0;
public int[] getIdValue2() {
return idValue2;
}
public void setIdValue2(int idValue2, int i) {
this.idValue2[i] = idValue2;
}
public int getId_case_info() {
return id_case_info;
}
public void setId_case_info(int id_case_info) {
this.id_case_info = id_case_info;
}
public int[] getIdValue1() {
return idValue1;
}
public void setIdValue1(int idValue1, int i) {
this.idValue1[i] = idValue1;
}
I need add to my Insert value from this method getIdValue1(), how can I do that? I think, there must be some sort of index, but I don't know how to use it.
Model it after your setIdValue2() method.
// You should check, somewhere, that i is a valid index of idValue2
public int getIdValue2(int i) {
return idValue2[i];
}
And now, you may call your method: int temp = getIdValue2(0); // Get item at first index
I'm trying to build some Dota2-like classes, with simple details. I got stuck at one point where I need my hero's attribute in Main, but the constructor for it doesn't work. Here is the code for Hero class:
enum attribute {
Strength, Intelligence, Agility
};
public class Hero extends Unit {
private int level;
private static int str;
private static int intl;
private static int agi;
private static attribute heroAttribute;
public attribute getAttribute() {
return heroAttribute;
}
private static int attributeDamage() {
if (heroAttribute == attribute.Strength)
return str;
else if (heroAttribute == attribute.Intelligence)
return intl;
else
return agi;
}
public Hero(int level, int str, int intl, int agi, attribute heroAttribute) {
super(200 + 20 * str, attributeDamage());
System.out.println("A hero has been spawned.");
}
}
and the Main:
public class Main {
public static void main(String[] args) {
Hero h1= new Hero(25,400,30,30,attribute.Agility);
System.out.println(h1.getAttribute());
}
}
What I get is that I have null "attribute" value.
Try put this attributes without the static, and initiate these attributes...
private int str;
private int intl;
private int agi;
private attribute heroAttribute;
public Hero(int level, int str, int intl, int agi, attribute heroAttribute) {
this.str = str;
this.intl = intl;
this.ai = agi;
this.heroAttribute = heroAttribute;
super(200 + 20 * str, attributeDamage());
System.out.println("A hero has been spawned.");
}
i suggest you to create new enum class that containt those 3 attribute and then, implement them.
by the way, all enum entities should be upper case like: STRENGTH, AGILITY, INTELLIGENT
public enum HeroAttribute {
STRENGTH("str"),
AGILITY("agi"),
INTELLIGENT("intl");
private String literal;
HeroAttribute(String literal) {
this.literal = literal;
}
public String getLiteral() {
return literal;
}
}
So i am trying to generate a house(at this point a very simple house) and I have this Class:
public class Probability {
public final int MinWindows = 0;
public final int MaxWindows = 0;
//double values represend the percent chance for a specific attribute to
//generate
public final double hasBackDoor = 0;
public final double hasSecondFloor = 0;
public final double hasChimny = 0;
public final double hasGarage = 0;
public final double hasPorch = 0;
}
This class is then inherited by subclasses for different types of houses:
public class LowClassHouseProbability extends Probability{
public final int MinWindows = 5;
public final int MaxWindows = 10;
public final double hasBackDoor = 55.0;
public final double hasSecondFloor = 10.0;
public final double hasChimny = 5.5;
public final double hasGarage = 30.0;
public final double hasPorch = 60.0;
}
public class MiddleClassHouseProbability extends Probability{
public final int MinWindows = 20;
public final int MaxWindows = 50;
public final double hasBackDoor = 80.0;
public final double hasSecondFloor = 70.0;
public final double hasChimny = 10.0;
public final double hasGarage = 90.0;
public final double hasPorch = 85.0;
}
public class UpperClassHouseProbability extends Probability{
public final int MinWindows = 50;
public final int MaxWindows = 100;
public final double hasBackDoor = 100.0;
public final double hasSecondFloor = 100.0;
public final double hasChimny = 80.0;
public final double hasGarage = 99.0;
public final double hasPorch = 100.0;
}
So all of the subclasses of Probability shadow all of its fields which in my opinioin looks sloppy and is kind of annoying to read, however i need them to extend Probability because it would make it easyer when i actually have to use the object, because it looks nicer doing this:
public class House {
public House(Probability prob){
}
}
Than if i did not have a Probability class and did this:
public class House {
public House(LowClassHouseProbability prob){
}
public House(MiddleClassHouseProbability prob){
}
public House(UpperClassHouseProbability prob){
}
}
And this would only get worse with the more sub-classes that I create.
So my question is is there a better way of doing this that I'm not thinking of, or do i just have to do it one way or the other of the two solutions that I thought of.
Since you can not override fields from the super class in java those classes dont need at all to define the field..
public class LowClassHouseProbability extends Probability{
//public final int MinWindows = 50;
//public final int MaxWindows = 100;
those all are final declared so you need to set those in the constructor...
LowClassHouseProbability(int minW, int maxW,...){
super(minW, maxW, ....);
MiddleClassHouseProbability(int minW, int maxW,...){
super(minW, maxW, ....);
UpperClassHouseProbability(int minW, int maxW,...){
super(minW, maxW, ....);
and in the superclass Probability define the constructor:
Probability(int minW, int maxW,...){
MinWindows = minW;
MaxWindows = maxW;
// .... etc etc
It's probably best to remove the child classes altogether and define instances of the Probability class pertinent to your house types, and build a multi-argument constructor to facilitate instance construction.
Alternatively, you could refactor this into an interface:
public interface Probability {
int getMinWindwsMinWindows();
/*and so on*/
}
Then,
public class LowClassHouseProbability implements Probability{
{
#Override
int getMinWindwsMinWindows()
{
return 5;
}
/*and so on*/
}
The problem of managing constructors with too many fields can be solved by using a step builder. A step builder works by creating an interface for each step, then having the builder implement all of them. This way after completing each build step, only the next step is available to complete.
Here's an example:
package mcve;
public class Probability {
public final int minWindows;
public final int maxWindows;
public final double hasBackDoor;
public final double hasSecondFloor;
public final double hasChimny;
public final double hasGarage;
public final double hasPorch;
private Probability(final int minWindows,
final int maxWindows,
final double hasBackDoor,
final double hasSecondFloor,
final double hasChimny,
final double hasGarage,
final double hasPorch) {
this.minWindows = minWindows;
this.maxWindows = maxWindows;
this.hasBackDoor = hasBackDoor;
this.hasSecondFloor = hasSecondFloor;
this.hasChimny = hasChimny;
this.hasGarage = hasGarage;
this.hasPorch = hasPorch;
}
public static final Probability LOW_CLASS =
builder().setMinWindows(5)
.setMaxWindows(10)
.setHasBackDoor(55.0)
.setHasSecondFloor(10.0)
.setHasChimny(5.5)
.setHasGarage(30.0)
.setHasPorch(60.0)
.build();
// public static final Probability MIDDLE_CLASS = ...;
// public static final Probability UPPER_CLASS = ...;
public static MinWindowsStep builder() {
return new Builder();
}
public interface MinWindowsStep { MaxWindowsStep setMinWindows(int n); }
public interface MaxWindowsStep { HasBackDoorStep setMaxWindows(int n); }
public interface HasBackDoorStep { HasSecondFloorStep setHasBackDoor(double n); }
public interface HasSecondFloorStep { HasChimnyStep setHasSecondFloor(double n); }
public interface HasChimnyStep { HasGarageStep setHasChimny(double n); }
public interface HasGarageStep { HasPorchStep setHasGarage(double n); }
public interface HasPorchStep { BuildStep setHasPorch(double n); }
public interface BuildStep { Probability build(); }
private static final class Builder
implements MinWindowsStep,
MaxWindowsStep,
HasBackDoorStep,
HasSecondFloorStep,
HasChimnyStep,
HasGarageStep,
HasPorchStep,
BuildStep {
private int minWindows;
private int maxWindows;
private double hasBackDoor;
private double hasSecondFloor;
private double hasChimny;
private double hasGarage;
private double hasPorch;
#Override
public MaxWindowsStep setMinWindows(int minWindows) {
this.minWindows = minWindows;
return this;
}
#Override
public HasBackDoorStep setMaxWindows(int maxWindows) {
this.maxWindows = maxWindows;
return this;
}
#Override
public HasSecondFloorStep setHasBackDoor(double hasBackDoor) {
this.hasBackDoor = hasBackDoor;
return this;
}
#Override
public HasChimnyStep setHasSecondFloor(double hasSecondFloor) {
this.hasSecondFloor = hasSecondFloor;
return this;
}
#Override
public HasGarageStep setHasChimny(double hasChimny) {
this.hasChimny = hasChimny;
return this;
}
#Override
public HasPorchStep setHasGarage(double hasGarage) {
this.hasGarage = hasGarage;
return this;
}
#Override
public BuildStep setHasPorch(double hasPorch) {
this.hasPorch = hasPorch;
return this;
}
#Override
public Probability build() {
return new Probability(minWindows,
maxWindows,
hasBackDoor,
hasSecondFloor,
hasChimny,
hasGarage,
hasPorch);
}
}
}
Fields have to be assigned by name, and if you forget which step you are on, the compiler error will tell you:
// This will cause an error with a message something like
// "Cannot find symbol method build() in interface MinWindowsStep".
Probability p = Probability.builder()
.build();
If it turns out that it really is the case that you need to use inheritance, the builder pattern can be adapted to that by having e.g. an abstract build step with multiple implementations.
import java.util.list;
import java.util.*;
public class PatientRecordSystem
{
private int PATIENTMAX = 100;
private int OBSERVATIONMAX = 50;
private int current = 1;
private int observationcurrent = 1;
// current = patients, observationcurrent = observations count
public PatientRecordSystem()
{
addPatient();
}
public void String addMeasurementObservationType()
{
}
public void String addCategoryObservationType()
{
}
public void String addPatient()
{
String PatientName = "James";
String PatientID = "10122";
}
public void String addMeasurementObservation()
{
// for patient
}
public void String addCategoryObservation()
{
// for patient
}
// no interactive inputs, all static details.
}
}
i'm unsure as to what is causing the error to appear as :
PatientRecordSystem.java:17: error: '(' expected
public void String addMeasurementObservationType()
^ PatientRecordSystem.java:22: error: '(' expected
public void String addCategoryObservationType()
^ PatientRecordSystem.java:27: error: '(' expected
public void String addPatient()
^ PatientRecordSystem.java:34: error: '(' expected
public void String addMeasurementObservation()
^ PatientRecordSystem.java:39: error: '(' expected
public void String addCategoryObservation()
The first issue is in your method declarations, you cannot declare your methods public void String
If your method returns nothing then it should be declared :
public void addMeasurementObservationType(){
// ...
}
If your method returns a String then it should be declared :
public String addMeasurementObservationType(){
return "the string to return";
}
The second one is that you are importing java.util.list;
You should import :
import java.util.List;
The third one is that you have an extra }
public void addCategoryObservation(){
// for patient
} <--- HERE
// no interactive inputs, all static details.
}
My guess is that your code should look like :
class PatientRecordSystem {
private int PATIENTMAX = 100;
private int OBSERVATIONMAX = 50;
private int current = 1;
private int observationcurrent = 1;
public PatientRecordSystem(){
addPatient();
}
public void addMeasurementObservationType(){
}
public void addCategoryObservationType(){
}
public void addPatient(){
String PatientName = "James";
String PatientID = "10122";
}
public void addMeasurementObservation(){
// for patient
}
public void addCategoryObservation(){
// for patient
// no interactive inputs, all static details.
}
}
you have something like this:
public void String addMeasurementObservationType()
{
}
and this is a contradiction/ makes no sense, your method should either return a String or just return nothing at all(void)
fix it by removing the String in the method return type
Example
public void addMeasurementObservationType()
{
}
and this apply for all the methods with the same error...
You can't have multiple return types. If you declare void as your return type you can't return anything... i have modified your code to return type as void. (change accordingly!) hope it helps...
public class PatientRecordSystem {
private int PATIENTMAX = 100;
private int OBSERVATIONMAX = 50;
private int current = 1;
private int observationcurrent = 1;
// current = patients, observationcurrent = observations count
public PatientRecordSystem() {
addPatient();
}
public void addMeasurementObservationType() {
}
public void addCategoryObservationType() {
}
public void addPatient() {
String PatientName = "James";
String PatientID = "10122";
}
public void addMeasurementObservation() {
// for patient
}
public void addCategoryObservation() {
// for patient
}
// no interactive inputs, all static details.
}
I believe my code is wrong but could someone correct me on my error. I am trying to deep clone an array of objects but class A doesn't seem to be a deep copy as i am having trouble with it. Could some please help. I have trouble copying the array A.
Class A implements Cloneable{
private int year;
private double data;
A(int year, double data)
{
setInt(year);
setDouble(data);
}
public void setInt(int year)
{
this.year = year;
}
public void setDouble(double data)
{
this.data = data;
}
public int getYear()
{
return year;
}
public double getData()
{
return data;
}
public Object clone()
{
A clonedA = new A(this.getYear(), this.getData());
return clonedA;
}}
class B implements Cloneable{
private A[] a;
private String name;
private int arraylength;
private int index;
public B(String name, int length)
{
this.name = name;
this.arraylength = length;
a = new A[array.length];
index = 0;
}
public void addToA(int year, double data)
{
a[index] = new A(year, data);
index++;
}
public String getName(){
return name; }
public int getLength(){
return array length;}
public void setName(String name)
{
this.name= name
}
public Object clone()
{
B clonedB = new B(this.getName(), this.getLength());
for(A clonedArray: a)
{
clonedB.addToA(clonedArray.getYear(), clonedArray.getData());
}
return clonedB;
}
Your clone method in class B seems to be wrong:
I suggest you do sth like
public Object clone()
{
B newB = new B(this.getName(), this.getLength());
for(int i =0;i<newB.a.length;i++)
{
newB.a[i] = a[i];
}
return newB;
}
You could also try a copy constructor;