I'm working on updating an old Java application to work on modern operating systems and I've run into an error that I can't figure out. I don't have much experience with Java but from what I've read, you can't store boolean values in an integer (1 or 0) like in C++.
Here's the bit of code where the error is:
public static double a(cr paramcr, int paramInt) {
double d = 0.0D;
int i = ++b;
if (b <= l.length()) {
if (paramInt < 0) {
int j = b; // <----------- defined again as an integer.
d = e();
if (e == true && d >= h && d + f - g >= 1.0D && d + f - g <= d) {
String str1 = String.valueOf((int)d);
d = d + f - g;
String str2 = String.valueOf((int)d);
l = a(j, l, str1, str2, i);
} else if (j == false) { // <---------------------------- error
if (((d < 1.0D || d > d) ? false : true) == false)
c = 7;
}
With error message:
The operator == is undefined for the argument type(s) int, boolean
The variable j is defined as a static boolean at the top of the program, but later redefined as an integer inside of this 'a' class. I notice that there are other integer variables being used to compare to true and false statements in this class, but they are all being compared to some condition in order to get a true or false result. That's obviously not the case here, and my problem is that I can't think of a way that this program would have ever functioned in the past if this is how it was written. Any ideas as to why this could be or suggestions on my next move?
It doesn't help that none of this has any documentation or intuitive variable names.
In Java you cannot treat an int as a boolean. Period.
I was sent some files that I was told contained the source code. It did not. I was then told to decompile it.
What you are apparently looking at is some code that has been decompiled from a ".class" file. Decompilation is NOT guaranteed to produce valid (compilable) Java source code. And in this case, it appears that it hasn't. Indeed, there are clues in that code that imply that the original bytecodes were obfuscated ... to deliberately make it hard for the decompiler to generate readable / valid Java source code.
(The problem is that the same bytecodes are used dealing with boolean and integer types up to int. In this case, the decompiler has assumed that the local variable is an int, and not been able to figure out that its assumption was incorrect. A better decompiler might be able to figure it out ...)
So what you will need to do is figure out how to modify that (not-really-Java) code to make it 1) compilable, and 2) do the correct thing1.
It doesn't help that none of this has any documentation or intuitive variable names.
Well ... that what happens when you try to use decompiled code. All local variable names and comments (including javadocs) are discarded by the compiler, and the decompiler has no way to reconstruct them.
The alternative is to go back to the people who were supposed to give you the source code and ask them to provide it to you ... for real!
1 - This assumes that you can figure out what this method is really supposed to be doing. I don't think we can help you with that. For a start, it would probably be necessary to read the disassembled bytecodes to figure out what the code really does.
Related
Occasionally, new users encounter the following rather obscure compilation error '.class' expected:
double d = 1.9;
int i = int d; // error here
^
error: '.class' expected
Some Java IDE compilers state this slightly differently; e,g,
error: insert ". class" to complete Expression
What do errors like this actually mean, what causes them, and how should you fix them?
First of all, this is a compilation error. If you see the message it at runtime, you are probably running code that has compilation errors.
Here are a couple of examples of the error:
double d = 1.9;
int i = int d; // error here
^
int j = someFunction(int[] a); // error here
^
In both cases, the compiler error message will be error: '.class' expected.
What does the error message mean and what causes it?
The compiler has gotten rather confused during syntax checking by some code that is (frankly) nonsensical. The compiler has encountered a type (e.g. int or int[]) in a context where it was actually expecting an expression. It is then saying that the only symbols that would be syntactically acceptable at this point would be . followed by class.
Here is an example where this syntax would be correct;
Class<?> clazz = int; // incorrect
Class<?> clazz = int.class; // correct!
Note: It should always be possible to figure out why the compiler's syntax checker thinks the type should be an expression. However, it is often simpler to just treat this as "the compiler is confused" and look for the (inevitable!) syntax error that caused the confusion. That syntax error may not be obvious ... to a beginner ... but knowing that this is the root cause is a good start.
How do you fix it?
Unfortunately, the "suggestion" of adding .class is almost always incorrect. It certainly won't help in the two examples at the start of this Answer!
The actual fix depends on what you were trying to achieve by putting the type there.
If you were intending to write a type cast, then you need to put parentheses (round brackets) around the type; e.g.
double d = 1.9;
int i = (int) d; // Correct: casts `1.9` to an integer
If you were simply intending to assign a value or pass a parameter as-is, then the type should be removed.
int j = someFunction(a); // Correct ... assuming that the type of
// 'a' is suitable for that call.
You need to specify the type of a formal parameter when declaring a method. But you usually don't need to specify it for the actual argument. In the rare situations where you do (to resolve overload ambiguity), you use a type cast.
More examples
someMethod(array[]);
The error is reported on array[] because that is a type not an expression. The correction would probably be either:
someMethod(array); // pass ref to the entire array
or
someMethod(array[someExpression]); // pass a single array element
int i = someMethod(int j);
The programmer has put a parameter declaration into a method call. An expression is required here, not a declaration:
int i = someMethod(j);
int i = int(2.0);
The programmer was trying to do a typecast. It should be written like this:
int i = (int) 2.0;
int[]; letterCount = new int[26];
The programmer has added a spurious semicolon. It should be written like this:
int[] letterCount = new int[26];
if (someArray[] > 80) {
// ...
}
The someArray[] denotes a type not an expression. The programmer probably means something like someArray[someIndex] > 80 or someArray.length > 80.
int[] integers = new int[arraySize];
...
return integers[];
The integers[] denotes a type declarator but an expression is required. It should be either
return integers; // Return the entire array
or
return integers[someIndex]; // Return one element of the array
if ((withdraw % 5 == 0) && (acnt_balc >= withdraw + 0.50))
double cur = acnt_balc - (withdraw + 0.50);
System.out.println(cur);
else
System.out.println(acnt_balc);
The mistake here is that there should be curly brackets around the "then" statements.
if ((withdraw % 5 == 0) && (acnt_balc >= withdraw + 0.50)) {
double cur = acnt_balc - (withdraw + 0.50);
System.out.println(cur);
} else {
System.out.println(acnt_balc);
}
But the compiler's confusion is that the "then" clause of the "if" cannot be a variable declaration. So the parser is looking for an expression that could be a method call. For example, the following would be locally syntactically valid:
if ((withdraw % 5 == 0) && (acnt_balc >= withdraw + 0.50))
double.class.newInstance(); // no compilation error here
... albeit nonsensical in terms of what it tries to do. And of course the compiler would then trip over the dangling else.
I don't understand why I get a compile error. In my view, this method first evaluates whether n is > 0. When this is the case, then "good" will be assigned to the String object local. However, if this is not the case, then it will not do anything. Next, the method enters another decision construct. This time, it evaluates whether n <= 0. If so, it will assign "bad" to the String object.
In any of both cases, local should be initialized. However, I get a compile error, and the compiler says it may not be initialized. I do not understand where this is coming from.
Note that I know how to correct the second if by replacing it with else and removing the boolean condition. I just don't understand why in a syntax sense this is incorrect.
public class Donkey{
String s1 = "green";
public void generateReport(int n){
String local;
if(n > 0)
local = "good";
if(n <= 0)
local = "bad";
System.out.println(local);
}
The compiler has no way to 'know' that you've handled all the cases with your if statements.
Consider this example (note that the second if is just less than):
String local;
if(n > 0)
local = "good";
if(n < 0)
local = "bad";
If n = 0, then local will not get defined.
The compiler doesn't test your if statements to see if they handle all the cases while compiling.
Changing it to if/else will fix the error as you mentioned. You can also initialize the variable as other users have pointed out.
The problem is that if n is not greater than 0 and is not less or equal than 0 the var local is not initialized. So that is what the compiler is telling you.
You can solve this by initializing the local var with something.
String local = "";
The problem is solved when you use else because for the compiler there can be only 2 possible states, the one if the condition is true and the other if is not, there is no possible third state because the else contemplates all.
i was trying to write some C++ codes into java, now i have writter following code into java but it is throwing errors!
if(ShapeNotFound && xd*yd - nPixel[k] < xd+yd) // Condition for RECTANGLE
{
System.out.print("\n "+in+" \t Rectangle \n");
fileWriter3.write("\n "+in+" \t Rectangle \n");
Shape[k] = 2;
ShapeNotFound = 0;
}
I am getting following error :
The operator && is undefined for the argument type(s) int, boolean
Please help, tell me how to write the above if condition correctly in java
C and C++ both assume that for integers 0 is false and all other values are true.
Java does not make the same assumption so you need to add a check for int!=0 into the expression i.e.:
if((ShapeNotFound!=0) && (xd*yd - nPixel[k] < xd+yd))
Or alternatively your ShapeNotFound variable should be of type boolean not int.
It would be worth converting variable names etc to Java style guidelines as well.
Java can not convert int into boolean automatically.
It looks like ShapeNotFound is an integer, but you're implicitly treating it like a boolean (true or false). Java only likes genuinely boolean expressions, so you'll need to change the condition to something like this:
if (ShapeNotFound != 0 && xd*yd - nPixel[k] < xd+yd)
For readability, I'd suggest putting some brackets round each part of the condition. That's an issue of personal preference though.
This might sound weird but I am struggling with this bug for past 2 days.
I have a boolean array in java that is initialised using a Random boolean generator.
After that the boolean array is acted upon by a function in C (called using JNI) and the modified boolean array is returned to java. When I hand over the boolean array to C, it is converted to unsigned char and converted back to jbooleanArray before being handed back to java.
Now I run the following code (there is a for loop over i):
if(chosen_packet[i] == false)
{
pkt.first[i] = 0;
System.out.print(chosen_packet[i]);
}
if(chosen_packet[i] == true)
{
pkt.first[i] = 1;
System.out.print(chosen_packet[i]);
}
The problem is that sometimes when chosen_packet[i] is true it still does not enter the second if condition. This happens sometimes and sometimes the code works just fine. When I print chosen_packet[i] in such a case it is printed as true yet it does not enter the second if condition. What could be the possible reason for this seeming corruption of the boolean array ?
EDIT: This is how I convert the boolean array to unsigned char in C:
jboolean *element = (*env)->GetBooleanArrayElements(env,chosen_packet,0);
for(j = 0; j < sz; j++)
src_pkt[j] = (unsigned char)element[j];
This src_pkt is acted upon and then I convert it back to jboolean .
EDIT2: This is how I convert the unsigned char array back to jboolean:
jbooleanArray arr = (*env)->NewBooleanArray(env,sz);
(*env)->SetBooleanArrayRegion(env,arr,0,sz,src_pkts);
(*env)->DeleteLocalRef(env,arr);
It's normal that if the boolean is true it does not enter in the first if since you are checking for it to be false in its condition.
Your code can be simplified to (you should use if/else instead of two if checking for the different conditions).
if (chosen_packet[i]) {
pkt.first[i] = 1;
} else {
pkt.first[i] = 0;
}
System.out.print(chosen_packet[i]);
or even
pkt.first[i] = chosen_packet[i] ? 1 : 0;
System.out.print(chosen_packet[i]);
Edit
If your program does not enter the second if, it means that the the var chosen_packet[i] is not true, you could use a debugger to verify what is the real value.
As stated by fredcrs, are you sure that chosen_packet[i] is of type boolean?
Java boolean is usually implemented as single byte. So it is possible that there is a bug in your C code that causes the boolean to be neither true nor false. In that case you may encounter undefined behavior.
Note that simply casting unsigned char to jboolean as in(jboolean) src_pkt[j] does not normalize it. You have to use src_pkt[j] ? JNI_TRUE : JNI_FALSE.
Still I believe you have to post more of relevant parts of your JNI code.
All,
In a bid to improve my C skills, I decided to start implementing various Java libraries/library functions to C code. This would ensure that everyone knows the functionality of my implementation at least. Here is the link to the C source code that simulates the equalsIgnoreCase() of String class in Java : C source code. I have tested the code and it looks fine as per my testing skills are concerned. My aim was to use as much basic operations and datatypes as possible. Though, it would be great if the gurus here can:
1 > Give me any suggestion to improve the code quality
2 > Enlighten me with any missing coding standard/practices
3 > Locate bugs in my logic.
100 lines of code is not too long to post here.
You calculate the string length twice. In C, the procedure to calculate the string length starts at the beginning of the string and runs along all of it (not necessarily in steps of 1 byte) until it finds the terminating null byte. If your strings are 2Mbyte long, you "walk" along 4Mbyte unnecessarily.
in <ctype.h> there are the two functions tolower() and toupper() declared. You can use one of them (tolower) instead of extractFirstCharacterASCIIVal(). The advantage of using the library function is that it is not locked in to ASCII and may even work with foreign characters when you go 'international'.
You use awkward (very long) names for your variables (and functions too). eg: ch1 and ch2 do very well for characters in file 1 and file 2 respectively :-)
return 1; at the end of main usually means something went wrong with the program. return 0; is idiomatic for successful termination.
Edit: for comparison with tcrosley version
#include <ctype.h>
int cmpnocase(const char *s1, const char *s2) {
while (*s1 && *s2) {
if (tolower((unsigned char)*s1) != tolower((unsigned char)*s2)) break;
s1++;
s2++;
}
return (*s1 != *s2);
}
With C++, you could replace performComparison(char* string1, char * string2) with stricmp.
However stricmp is not part of the standard C library. Here is a version adapted to your example. Note you don't need the extractFirstCharacterASCIIVal function, use tolower instead. Also note there is no need to explicitly calculate the string length ahead of time, as strings in C are terminated by the NULL character '\0'.
int performComparison(char* string1, char * string2)
{
char c1, c2;
int v;
do {
c1 = *string1++;
c2 = *string2++;
v = (UINT) tolower(c1) - (UINT) tolower(c2);
} while ((v == 0) && (c1 != '\0') && (c2 != '\0') );
return v != 0;
}
If you do want to use your own extractFirstCharacterASCIIVal function instead of the tolower macro, to make the code more transparent then you should code it like so:
if ((str >= 'a') && (str <= 'z'))
{
returnVal = str - ('a' - 'A');
}
else
{
returnVal = str;
}
to make it more obvious what you are doing. Also you should include a comment that this assumes the characters a..z and A..Z are contiguous. (They are in ASCII, but not always in other encodings.)