Click to See Complete Forum and Search --> : String.replaceAll problem


Martin O
October 12th, 2004, 03:38 PM
I got a 'java.lang.NoSuchMethodError' when I used String.replaceAll. I got this at runtime not compile time. The reason is that when the prog was run it was run with version 1.3 of java, but I compiled it with version 1.4.

So I thought, to prevent this from happening I should add -target 1.3 to my javac command. Then rather than a runtime error, I'd get a compiler error. I did that, but I still get no compiler error (even after removing all class files). I also tried -source 1.3 & it didn't work (in other words--it compiled fine)

1. What exacly does -target & -source do?
2. Why don't I get a compiler error when I call String.replaceAll and compile with javac -target 1.3 (or -source 1.3).
3. Is there any easy replacement for 'replaceAll'? For instance I want to replace 'a' with 'abc'

Thanks.

jw_wvu
October 12th, 2004, 03:57 PM
I'm not sure what the -target directive is supposed to do.

Probably the reson that it didn't behave the way you thought it should was because of your CLASSPATH variable, but that is just my gut feeling.

Have you looked at the String.replace() method instead of the String.replaceAll() method?

I'm assuming that you have a good reason for compiling under one version of JAVA and running under another?!

Martin O
October 12th, 2004, 04:12 PM
Probably the reson that it didn't behave the way you thought it should was because of your CLASSPATH variable, but that is just my gut feeling.


Actually I don't have any CLASSPATH environment var. And there's no -classpath on the javac command line


Have you looked at the String.replace() method instead of the String.replaceAll() method?


Yes but that only lets me replace a char with a char. I need to replace a char with a string.


I'm assuming that you have a good reason for compiling under one version of JAVA and running under another?!

I'm writing code for a Palm PDA Conduit. The conduit uses java 1.3 and I don't think I can change that.

Thanks.

jw_wvu
October 12th, 2004, 04:35 PM
here is a quick and dirty solution:


package testing;


public class StringTest
{
String theData;

public StringTest()
{
theData = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
}

public void myTranslate( String target )
{
// replace all the 'lmn' with the text JAVA

String dataBeforeTarget;
String dataAfterTarget;

int loc = theData.indexOf(target);
while (loc != -1)
{
dataBeforeTarget = theData.substring(0, loc);
dataAfterTarget = theData.substring(loc + target.length());

theData = dataBeforeTarget + "JAVA" + dataAfterTarget;

loc = theData.indexOf(target);
}

}

public static void main(String[] args)
{
StringTest st = new StringTest();

System.out.println("before translation " + st.theData);

st.myTranslate( "lmn" );

System.out.println("after translation: " + st.theData);
}
}

dlorde
October 12th, 2004, 05:35 PM
String.replaceAll(...) was introduced in JDK 1.4. You must use a compiler no earlier than version 1.4 and a runtime no earlier than version 1.4 if you want to use it. Only a 1.4 compiler (or later) can compile the instructions to call this method, and only a 1.4 runtime (or later) can provide the code that implements this method.

If you must use an earlier runtime than 1.4, you can use a later compiler, but you must only use features available under 1.3. If you need a replaceAll(...) method, you will have to write one yourself or find a JDK 1.3 compatible proprietary library that provides it.

Doing more things faster is no substitute for doing the right things...
R. Covey

Martin O
October 13th, 2004, 08:29 AM
Thanks jw_wvu and dlorde.

I understand that I can only use <= 1.3 functions if I'm targeting java 1.3. I just thought that I could use javac -target 1.3 or -source 1.3 to give me the errors at compile time instead of run time. Otherwise, I've got to keep my eye on the 'Since' part of the java docs.

cjard
October 13th, 2004, 10:56 AM
1. What exacly does -target & -source do?
-target causes class files to be generated in a particular format. With each release of java, the format of the class file changes slightly. a -target 1.4 generated class will only work on 1.4 jvm because the only classloaders capable of reading the file are classloaders of at least v 1.4

an analogue could be microsoft word:
-target 97 generates you a word97 file
-target 2000 generates you a word 2000 file
-target xp generates you a word XP file

word XP (the program), can read word97 files. word97 (the program)cannot read word XP files. if you -target 1.3 then you will need at least jvm 1.3 to load that class file, else youll probably get a BadMagicNumber error.

the java compiler is abosolutely ignorant of the dependncies and @since of the java core files. why? because java is bigger than just sun's core libraries. the java 1.4 compiler has no knowledge of what is and is not available in non-1.4 java.. because its a huge task to do. if sun did it for their own classes, then they would have to do it for everyones custom third party classes

------

-source specifies what junk the compiler can expect to find in the code. -source 1.3 specifies that it will be pure java as per original java 1.3 spec
-source 1.4 specifies it has the added junk of assertions. if you wish to disable assertions, then you can program your assertion-ridden code and load it into the compiler with -source 1.3.. the compiler will ignore assertions
im not sure, but theres probably an analogue for 1.5; it added a raft of syntactical "improvements" that can probably be compiled against or for, using the source tag. but im not sure


------

at the end of the day, the simple advice is:

if your target system is 1.3, then install and develop with 1.3 on your pc. it is still available in the archived releases of java


2. Why don't I get a compiler error when I call String.replaceAll and compile with javac -target 1.3 (or -source 1.3).
see above comment about the compiler being ignorant of @since sirectives. if you wish, you can write a program to check for these yourself, but you have the huge task of figuring out which classes are sun, and which arent, and which are extensions of sun.. then you have to parse the javadoc for that particular class, and read the @since parameter and...

headaches.. just install 1.3 on your pc


3. Is there any easy replacement for 'replaceAll'? For instance I want to replace 'a' with 'abc'
write it yourself;
repeatedly call indexOf() to:
find 'a'
store 'a's location
substring to that point, splice in new string + substring to end
add length of new string to store (prevents infinite loop of finding 'a' in 'abc')
continue indexOf from that location


Thanks.
no problem

cjard
October 13th, 2004, 11:09 AM
something like this: this algorithm might ned tweaking because i jsut pulled it straight out of my head without thinking about it too much..

StringBuffer sb = new StringBuffer(N);
int idx;
int lastLocation = 0;
for(idx = ORIG.indexOf(FIND); idx != -1; idx = ORIG.indexOf(FIND)){
//cut section from start to index into the buffer
sb.append( ORIG.substring(0, idx) );
//put new strng in buffer
sb.append( NEW );
//chop bit we already examined, plus the lenght of the found string
lastLocation = idx + FIND.length()
ORIG = ORIG.substring( lastLocation );
}

//insert the trailing part of the string
sb.append(ORIG.substring(lastLocation));

ORIG is the original string, FIND is the string to find, NEW is the replacement string

this algo differs from the one i posted above (we add find.length() not new.length() ) because it starts with string X and progressively cuts it from start to finish, into a buffer. indexOf always searches from 0 rather than a last found index, and because it is always only ever searching a portion of the original string (with no new added bits) we dont think about avoiding searching any texts inserted by us

cat.skinWays() > 1

Martin O
October 13th, 2004, 11:18 AM
Thanks cjard. That totally clears up -target & -source for me & why it won't work the way I expect. Thanks for the function too.