groovy.lang.MissingMethodException String vs java.lang.String - string

I was doing a coding challenge that prints a given text in a zig-zag:
thisisazigzag:
t a g
h s z a
i i i z
s g
So I have my code (not sure if it's right or not yet, but that's not part of the question)
class Main {
public void zigzag(String text, int lines) {
String zigLines = [];
while(lines > 0){
String line = "";
increment = lines+(lines-2);
lines = lines + (" " * (lines-1));
for(int i=(lines-1); i<text.length(); i+=increment) {
line = line + text[i] + (" " * increment);
}
zigLines.add(0, line);
lines--;
}
for(line in zigLines){
println(line);
}
}
static void main(String[] args) {
zigzag("thisisazigzag", 4);
}
}
But when I run the script, I keep getting this error:
groovy.lang.MissingMethodException: No signature of method: static Main.zigzag()
is applicable for argument types: (String, Integer) values: [thisisazigzag, 4]
Possible solutions: zigzag(java.lang.String, int)
And I'm very confused as to the difference between java.lang.String and String and then Integer and int?
Any help or explanation of this would be great!
Thanks.

You should make your zigzag method static.
Your code wasn't working because without the static modifier zigzag was an instance method, meaning you would need an instance of your class Main to be able to call it. Here's an introductory tutorial explaining some of these concepts: docs.oracle.com/javase/tutorial/java/javaOO/classvars.html

Related

Program to find if a string is a palindrome keeps on failing. Even after using toLowerCase() command for both strings, output doesn't come

import java.util.Scanner;
class Palindrome_string
{
public static void main()
{
System.out.println("\f");
Scanner sc = new Scanner(System.in);
System.out.println("Enter a string");
String a = sc.nextLine();
int b = a.length();
String rev = "";
for (int i = b - 1; i >= 0; i--)
{
char c = a.charAt(i);
rev = rev + c;
}
System.out.println("Original word "+a);
System.out.println("Reversed word "+rev);
a = a.toLowerCase();
rev = rev.toLowerCase();
if (a == rev)
{
System.out.println("It is a palindrome");
}
else
{
System.out.println("It is not a palindrome");
}
sc.close();
}
}
The program compiles properly. Still, when running the program, the message which tells if it is a palindrome prints incorrectly. What changes do I make? Here is a picture of the output. Even though the word 'level' (which is a palindrome) has been inputted, it shows that it isn't a palindrome. What changes should I make? output pic
You should not use == to compare two strings because it compares the reference of the string, i.e. whether they are the same object or not.
Use .equals() instead. It tests for value equality. So in your case:
if (a.equals(rev))
{
System.out.println("It is a palindrome");
}
Also try not to use single-letter variable names except for index variables when iterating over a list etc. It's bad practice.

Groovy primitive double arithmetic

This yields 127
double middle = 255 / 2
While this yields 127.5
Double middle = 255 / 2
Meanwhile this yields 127.5 as well
double middle = (255 / 2) as double
I know that Groovy operates with BigDecimal per default, but to me this is a Huuge bug! How can this be?
This actually has nothing to do with BigDecimals, but rather with the type coercion from primitive integer to the primitive double. This problem is caused by the Groovy compiler and the (most probably) incorrect bytecode it produces. Take a look at the following bytecode representation of the first case. The following Groovy code:
void ex1() {
double x = 255 / 2
println x
}
gets compiled to a bytecode that can be represented as:
public void ex1() {
CallSite[] var1 = $getCallSiteArray();
double x = 0.0D;
if (BytecodeInterface8.isOrigInt() && BytecodeInterface8.isOrigD() && !__$stMC && !BytecodeInterface8.disabledStandardMetaClass()) {
int var5 = 255 / 2;
x = (double)var5;
} else {
Object var4 = var1[5].call(255, 2);
x = DefaultTypeTransformation.doubleUnbox(var4);
}
var1[6].callCurrent(this, x);
}
It shows that in this case, it is not possible to get 127.5 as a result, because the result of 255 / 2 expression is stored in the variable of type int. It feels like this is an example of inconsistent behavior because here is what the bytecode of the method that uses Double looks like:
public void ex2() {
CallSite[] var1 = $getCallSiteArray();
Double x = null;
if (BytecodeInterface8.isOrigInt() && !__$stMC && !BytecodeInterface8.disabledStandardMetaClass()) {
Object var4 = var1[8].call(255, 2);
x = (Double)ScriptBytecodeAdapter.castToType(var4, Double.class);
} else {
Object var3 = var1[7].call(255, 2);
x = (Double)ScriptBytecodeAdapter.castToType(var3, Double.class);
}
var1[9].callCurrent(this, x);
}
The main problem with this use case is that adding #TypeChecked does not prevent you from making this mistake - compilation passes and the incorrect result is returned. However, when we add #TypeChecked annotation to the method that uses Double the compilation error is thrown. Adding #CompileStatic solves the problem.
I've run some tests and I can confirm that this problem exists in the recent 2.5.6, as well as 3.0.0-alpha-4 versions. I've created a bug report in the Groovy JIRA project. Thanks for finding and reporting the problem!
UPDATE: Java does the same
It seems like this is not a Groovy bug - this is how Java does things as well. In Java, you can store a result of a division of two ints in the double variable, but you will get nothing else than an integer cast to the double. With {{Double}} type things are different in terms of the syntax but pretty similar in terms of the bytecode. With {{Double}} you need to explicitly cast at least one part of the equation to the {{double}} type, which results in the bytecode that casts both integers to the {{double}}. Consider the following example in Java:
final class IntDivEx {
static double div(int a, int b) {
return a / b;
}
static Double div2(int a, int b) {
return a / (double) b;
}
public static void main(String[] args) {
System.out.println(div(255,2));
System.out.println(div2(255,2));
}
}
When you run it you get:
127.0
127.5
Now, if you take a look at the bytecode it creates, you will see something like this:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
final class IntDivEx {
IntDivEx() {
}
static double div(int a, int b) {
return (double)(a / b);
}
static Double div2(int a, int b) {
return (double)a / (double)b;
}
public static void main(String[] args) {
System.out.println(div(255, 2));
System.out.println(div2(255, 2));
}
}
The only difference (in terms of the syntax) between Groovy and Java is that Groovy allows you to implicitly cast an integer to Double, and that is why
Double x = 255 / 2
is the correct statement in Groovy, while Java, in this case, fails during the compilation with the following error:
Error:(10, 18) java: incompatible types: int cannot be converted to java.lang.Double
That is why in Java you need to use casting when you assign from integer to Double.

Chance for this hole in Groovy staic typing to be fixed

When I run the following Groovy snippet, it prints ",a,b,c" as expected:
#CompileStatic
public static void main(String[] args) {
def inList = ["a", "b", "c"]
def outList = inList.inject("", { a, b -> a + "," + b })
println(outList)
}
Now I change the first parameter in inject from an empty string to the number 0:
#CompileStatic
public static void main(String[] args) {
def inList = ["a", "b", "c"]
def outList = inList.inject(0, { a, b -> a + "," + b })
println(outList)
}
This won't work an produces an exception "Cannot cast object '0,a' with class 'java.lang.String' to class 'java.lang.Number'". Problem is that the compiler did not complain. I tried this in Scala and Kotlin (where inject is called fold) an the respective compiler complains about the mismatch as expected. Also the counterpart in Java8 does not compile (it says found int, required: java.lang.String):
List<String> list = Arrays.asList("a", "b", "c");
Object obj = list.stream().reduce(0, (x, y) -> x + y);
System.out.println(obj);
Question is now whether this can be fixed in Groovy or whether this is a a general problem because of static typing being introduced later into the language.
I think (I'm not 100% sure) that it is a bug in Groovy, very probably somewhere in type inference, and it can be fixed. Try to fill an issue in the bug tracker.
If you want to see compilation error, you can give types to closure parameters
inList.inject(0, { String a, String b -> a + "," + b })
Gives an error:
Expected parameter of type java.lang.Integer but got java.lang.String
# line 7, column 38.
def outList = inList.inject(0, { String a, String b -> a + "," + b})
^

Java Concept Confusion : Objects and Primitive Types

I am really confused about this concept:
/* Example with primitive data type */
public class Example1 {
public static void main (String[] args){
int a = 1;
System.out.println("a is " + a);
myMethod( a );
System.out.println("a is " + a);
}
public static void myMethod(int b){
b = 3;
System.out.println("b is " + b);
}
}
OUTPUT:
a is 1
b is 3
a is 1
Why does "a" not change?How does this primitive variable CHANGE like for a FOR LOOP or a WHILE LOOP when int i is initialed to zero? Like this:
int i = 1;
while (i < = 3) {
System.out.println(i);
i *= 2;
}
OUTPUT:
1
2
Please let me know in detail, as I am really confused.i is a primitive type, why does it get updated, and why does not int a in the first program?
myMethod() is void, if it returned an int and you assigned a=myMethod(a) then it would change
int a = 1;
System.out.println("a is " + a);
a= myMethod(a); //where myMethod is changed to return b instead of void
System.out.println("a is " + a);
a is 1
b is 3
a is 3
"Why does "a" not change?"
Because primitive a inside of your myMethod is not the same a that you had in your void main. Treat it as completely another variable and that its value got copied into myMethod. This primitive`s lifecycle ends in the end of this method execution.
If you have C++ background then maybe this explanation might help:
When you pass primitive type arguments into method - you are passing
variables that are being copied. You passed value, not instance.
When you pass objects as arguments
into method - you are passing references to that object, but to be more precise: in java, a copy of reference value is being passed. It is like passing a copy of the address of the object to the method. If you modify this object inside this method, the modifications will be visible outside the method. If you =null or =new Obj it, it will affect the object only inside your method.

Finding sub-strings in Java 6

I looked through the String API in Java 6 and I did not find any method for computing how many times a specific sub-string appears within a given String.
For example, I would like to know how many times "is" or "not" appears in the string "noisxxnotyynotxisi".
I can do the long way with a loop, but I would like to know whether there is a simpler way.
Thanks.
Edit: I'm using Java 6.
org.apache.commons.lang.StringUtils.countMatches method could be preferred.
Without using an external library, you can use String.indexOf(String str, int fromIndex); in a loop.
Update This example fully works.
/**
* #author The Elite Gentleman
* #since 31 March 2011
*
*/
public class Test {
private static final String STR = "noisxxnotyynotxisi";
public static int count(String str) {
int count = 0;
int index = -1;
//if (STR.lastIndexOf(str) == -1) {
// return count;
//}
while ((index = STR.indexOf(str, index + 1)) != -1) {
count++;
}
return count;
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Test.count("is"));
System.out.println(Test.count("no"));
}
}
You can do this, but a loop would be faster.
String text = "noisxxnotyynotxisinono";
String search = "no";
int count = text.split(search,-1).length-1;
System.out.println(Arrays.toString(text.split(search,-1)));
System.out.println("count= " + count);
prints
[, isxx, tyy, txisi, , ]
count= 5
As you can see this is correct if the text starts or ends with the search value. The -1 argument stops it removing trailing seperators.
You can use a loop with indexOf() which is more efficient, but not as simple.
BTW: Java 5.0 has been EOL since Aug 2007. Perhaps its is time to look at Java 6. (though the docs are very similar)

Resources