提交 0163a2a2 authored 作者: Thomas Mueller's avatar Thomas Mueller

Java to C converter (moving forward C++ will be used)

上级 b8c6a437
......@@ -204,6 +204,11 @@ class MethodObj {
*/
boolean isVirtual;
/**
* Whether this method is to be ignored (using the Ignore annotation).
*/
boolean isIgnore;
/**
* The name.
*/
......@@ -285,6 +290,11 @@ class FieldObj {
*/
boolean isPublic;
/**
* Whether this method is to be ignored (using the Ignore annotation).
*/
boolean isIgnore;
/**
* The initial value expression (may be null).
*/
......@@ -317,6 +327,15 @@ class Type {
*/
boolean isVarArgs;
/**
* Whether this is a non-array primitive type.
*
* @return true if yes
*/
public boolean isSimplePrimitive() {
return arrayLevel == 0 && classObj.isPrimitive;
}
public String toString() {
StringBuilder buff = new StringBuilder();
buff.append(JavaParser.toC(classObj.toString()));
......
......@@ -54,6 +54,16 @@ class CallExpr implements Expr {
StringBuilder buff = new StringBuilder();
String methodName;
initMethod();
if (method.isIgnore) {
if (args.size() == 0) {
// ignore
} else if (args.size() == 1) {
buff.append(args.get(0));
} else {
throw new IllegalArgumentException(
"Cannot ignore method with multiple arguments: " + method);
}
} else {
if (method.isVirtual) {
methodName = "virtual_" + method.name + "[CLASS_ID("+expr.toString()+")]";
} else {
......@@ -72,7 +82,9 @@ class CallExpr implements Expr {
i++;
buff.append(a);
}
return buff.append(")").toString();
buff.append(")");
}
return buff.toString();
}
public Type getType() {
......@@ -92,12 +104,17 @@ class AssignExpr implements Expr {
Expr right;
public String toString() {
if (left.getType().isSimplePrimitive()) {
return left + " " + op + " " + right;
}
if (right.toString().equals("null")) {
return "release(" + left + ")";
}
return left + " = set(" + left + ", " + right + ")";
}
public Type getType() {
// TODO
return null;
return left.getType();
}
}
......@@ -115,8 +132,7 @@ class ConditionalExpr implements Expr {
}
public Type getType() {
// TODO
return null;
return ifTrue.getType();
}
}
......@@ -288,6 +304,11 @@ class NewExpr implements Expr {
*/
class StringExpr implements Expr {
/**
* The constant name.
*/
String constantName;
/**
* The literal.
*/
......@@ -301,7 +322,7 @@ class StringExpr implements Expr {
}
public String toString() {
return "STRING(\"" + javaEncode(text) + "\")";
return constantName;
}
public Type getType() {
......@@ -407,13 +428,16 @@ class VariableExpr implements Expr {
private void init() {
if (field == null) {
if (base == null) {
System.out.println("??");
}
Type t = base.getType();
if (t.arrayLevel > 0) {
if ("length".equals(name)) {
field = new FieldObj();
field.type = context.getClassObj("int").baseType;
} else {
throw new RuntimeException("Unknown array method: " + name);
throw new IllegalArgumentException("Unknown array method: " + name);
}
} else {
field = t.classObj.getField(name);
......
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.java;
/**
* This annotation marks methods that are only needed for testing.
*/
public @interface Ignore {
// empty
}
......@@ -11,9 +11,11 @@ import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import org.h2.util.New;
/**
* Converts Java to C.
......@@ -27,11 +29,11 @@ public class JavaParser {
private static final int TOKEN_IDENTIFIER = 4;
private static final int TOKEN_OTHER = 5;
private static final HashSet<String> RESERVED = new HashSet<String>();
private static final HashMap<String, String> JAVA_IMPORT_MAP = new HashMap<String, String>();
private static final HashSet<String> RESERVED = New.hashSet();
private static final HashMap<String, String> JAVA_IMPORT_MAP = New.hashMap();
private final ArrayList<ClassObj> allClasses = new ArrayList<ClassObj>();
private final HashMap<String, ClassObj> builtInTypes = new HashMap<String, ClassObj>();
private final ArrayList<ClassObj> allClasses = New.arrayList();
private final HashMap<String, ClassObj> builtInTypes = New.hashMap();
private String source;
......@@ -42,12 +44,15 @@ public class JavaParser {
private int nextClassId;
private MethodObj method;
private FieldObj thisPointer;
private HashMap<String, String> importMap = new HashMap<String, String>();
private HashMap<String, ClassObj> classes = new HashMap<String, ClassObj>();
private HashMap<String, String> importMap = New.hashMap();
private HashMap<String, ClassObj> classes = New.hashMap();
private LinkedHashMap<String, FieldObj> localVars = new LinkedHashMap<String, FieldObj>();
private HashMap<String, MethodObj> allMethodsMap = new HashMap<String, MethodObj>();
private HashMap<String, MethodObj> allMethodsMap = New.hashMap();
private ArrayList<Statement> nativeHeaders = new ArrayList<Statement>();
private ArrayList<Statement> nativeHeaders = New.arrayList();
private HashMap<String, String> stringToStringConstantMap = New.hashMap();
private HashMap<String, String> stringConstantToStringMap = New.hashMap();
public JavaParser() {
addBuiltInTypes();
......@@ -279,6 +284,12 @@ public class JavaParser {
classObj.nativeCode.add(s);
}
thisPointer = null;
HashSet<String> annotations = New.hashSet();
while (readIf("@")) {
String annotation = readIdentifier();
annotations.add(annotation);
}
boolean isIgnore = annotations.contains("Ignore");
boolean isStatic = false;
boolean isFinal = false;
boolean isPrivate = false;
......@@ -301,6 +312,7 @@ public class JavaParser {
}
if (readIf("{")) {
method = new MethodObj();
method.isIgnore = isIgnore;
method.name = isStatic ? "cl_init_obj" : "init_obj";
method.isStatic = isStatic;
localVars.clear();
......@@ -313,6 +325,7 @@ public class JavaParser {
String typeName = readTypeOrIdentifier();
Type type = readType(typeName);
method = new MethodObj();
method.isIgnore = isIgnore;
method.returnType = type;
method.isStatic = isStatic;
method.isFinal = isFinal;
......@@ -347,6 +360,7 @@ public class JavaParser {
addMethod(method);
} else {
FieldObj field = new FieldObj();
field.isIgnore = isIgnore;
field.type = type;
field.name = name;
field.isStatic = isStatic;
......@@ -354,11 +368,6 @@ public class JavaParser {
field.isPublic = isPublic;
field.isPrivate = isPrivate;
field.declaredClass = classObj;
if (isStatic) {
classObj.addStaticField(field);
} else {
classObj.addInstanceField(field);
}
if (readIf("=")) {
if (field.type.arrayLevel > 0 && readIf("{")) {
field.value = readArrayInit(field.type);
......@@ -367,6 +376,11 @@ public class JavaParser {
}
}
read(";");
if (isStatic) {
classObj.addStaticField(field);
} else {
classObj.addInstanceField(field);
}
}
}
}
......@@ -409,7 +423,7 @@ public class JavaParser {
private void initThisPointer() {
thisPointer = new FieldObj();
thisPointer.isLocal = true;
thisPointer.name = "this";
thisPointer.name = "thiz";
thisPointer.type = new Type();
thisPointer.type.classObj = classObj;
}
......@@ -464,7 +478,7 @@ public class JavaParser {
private Statement readNativeStatementIf() {
if (readIf("//")) {
read();
boolean isC = readIdentifierIf("c");
int start = current.index;
while (source.charAt(current.index) != '\n') {
current.index++;
......@@ -472,9 +486,9 @@ public class JavaParser {
StatementNative stat = new StatementNative();
stat.code = source.substring(start, current.index).trim();
read();
return stat;
return isC ? stat : null;
} else if (readIf("/*")) {
read();
boolean isC = readIdentifierIf("c");
int start = current.index;
while (source.charAt(current.index) != '*' || source.charAt(current.index + 1) != '/') {
current.index++;
......@@ -483,7 +497,7 @@ public class JavaParser {
stat.code = source.substring(start, current.index).trim();
current.index += 2;
read();
return stat;
return isC ? stat : null;
}
return null;
}
......@@ -745,23 +759,30 @@ public class JavaParser {
LiteralExpr expr = new LiteralExpr(this, "boolean");
expr.literal = "false";
return expr;
}
if (readIf("true")) {
} else if (readIf("true")) {
LiteralExpr expr = new LiteralExpr(this, "boolean");
expr.literal = "true";
return expr;
}
if (readIf("null")) {
} else if (readIf("null")) {
LiteralExpr expr = new LiteralExpr(this, "java.lang.Object");
expr.literal = "null";
return expr;
}
if (current.type == TOKEN_LITERAL_NUMBER) {
} else if (current.type == TOKEN_LITERAL_NUMBER) {
// TODO or long, float, double
LiteralExpr expr = new LiteralExpr(this, "int");
expr.literal = current.token.substring(1);
readToken();
return expr;
} else if (current.type == TOKEN_LITERAL_CHAR) {
LiteralExpr expr = new LiteralExpr(this, "char");
expr.literal = current.token + "'";
readToken();
return expr;
} else if (current.type == TOKEN_LITERAL_STRING) {
String text = current.token.substring(1);
StringExpr expr = getStringConstant(text);
readToken();
return expr;
}
Expr expr;
expr = readExpr5();
......@@ -799,6 +820,47 @@ public class JavaParser {
return expr;
}
private StringExpr getStringConstant(String s) {
String c = stringToStringConstantMap.get(s);
if (c == null) {
StringBuilder buff = new StringBuilder();
for (int i = 0; i < s.length() && i < 16; i++) {
char ch = s.charAt(i);
if (ch >= 'a' && ch <= 'z') {
// don't use Character.toUpperCase
// to avoid locale problems
// (the uppercase of i isn't always I)
buff.append((char) (ch + 'A' - 'a'));
} else if (ch >= 'A' && ch <= 'Z') {
buff.append(ch);
} else if (ch == '_' || ch == ' ') {
buff.append('_');
}
}
c = buff.toString();
if (c.length() == 0 || stringConstantToStringMap.containsKey(c)) {
if (c.length() == 0) {
c = "X";
}
int i = 2;
for (;; i++) {
String c2 = c + "_" + i;
if (!stringConstantToStringMap.containsKey(c2)) {
c = c2;
break;
}
}
}
c = "STRING_" + c;
stringToStringConstantMap.put(s, c);
stringConstantToStringMap.put(c, s);
}
StringExpr expr = new StringExpr(this);
expr.text = s;
expr.constantName = c;
return expr;
}
private Expr readExpr5() {
if (readIf("new")) {
NewExpr expr = new NewExpr(this);
......@@ -822,12 +884,6 @@ public class JavaParser {
}
return expr;
}
if (current.type == TOKEN_LITERAL_STRING) {
StringExpr expr = new StringExpr(this);
expr.text = current.token.substring(1);
readToken();
return expr;
}
if (readIf("this")) {
VariableExpr expr = new VariableExpr(this);
expr.field = thisPointer;
......@@ -947,6 +1003,14 @@ public class JavaParser {
return result;
}
private boolean readIdentifierIf(String token) {
if (current.type == TOKEN_IDENTIFIER && token.equals(current.token)) {
readToken();
return true;
}
return false;
}
private boolean readIf(String token) {
if (current.type != TOKEN_IDENTIFIER && token.equals(current.token)) {
readToken();
......@@ -1123,6 +1187,7 @@ public class JavaParser {
case ',':
case '?':
case ':':
case '@':
break;
case '.':
if (source.charAt(current.index) == '.' && source.charAt(current.index + 1) == '.') {
......@@ -1159,7 +1224,8 @@ public class JavaParser {
}
break;
case '/':
if (source.charAt(current.index) == '*' || source.charAt(current.index) == '/') {
if (source.charAt(current.index) == '*' || source.charAt(current.index) == '/'
|| source.charAt(current.index) == '=') {
current.index++;
}
break;
......@@ -1318,7 +1384,9 @@ public class JavaParser {
}
out.println();
for (ClassObj c : classes.values()) {
out.println("/* " + c.className + ".h */");
out.println("struct " + toC(c.className) + ";");
}
for (ClassObj c : classes.values()) {
for (FieldObj f : c.staticFields.values()) {
StringBuilder buff = new StringBuilder();
buff.append("extern ");
......@@ -1336,21 +1404,36 @@ public class JavaParser {
buff.append(";");
out.println(buff.toString());
}
out.println("struct " + toC(c.className) + " {");
out.println("typedef struct " + toC(c.className) + " {");
for (FieldObj f : c.instanceFields.values()) {
out.print(" " + toC(f.type.toString()) + " " + f.name);
out.print(" ");
if (!f.type.classObj.isPrimitive) {
out.print("struct ");
}
out.print(toC(f.type.toString()) + " " + f.name);
if (f.value != null) {
out.print(" = " + f.value);
}
out.println(";");
}
if (c.instanceFields.size() == 0) {
out.println("int dummy;");
out.println(" int dummy;");
}
out.println("};");
out.println("typedef struct " + toC(c.className) + " " + toC(c.className) + ";");
out.println("} " + toC(c.className) + ";");
}
ArrayList<String> constantNames = New.arrayList(stringConstantToStringMap.keySet());
Collections.sort(constantNames);
for (String c : constantNames) {
String s = stringConstantToStringMap.get(c);
out.println("const java_lang_String* " + c + " = STRING(\"" + s + "\");");
}
for (ClassObj c : classes.values()) {
out.println("/* " + c.className + " */");
for (ArrayList<MethodObj> list : c.methods.values()) {
for (MethodObj m : list) {
if (m.isIgnore) {
continue;
}
out.print(m.returnType + " " + toC(c.className) + "_" + m.name + "(");
int i = 0;
if (!m.isStatic && !m.isConstructor) {
......@@ -1398,6 +1481,9 @@ public class JavaParser {
void writeSource(PrintWriter out) {
out.println("/* method pointers */");
for (MethodObj m : allMethodsMap.values()) {
if (m.isIgnore) {
continue;
}
out.print(m.returnType + " (*virtual_" + m.name + "[])(");
int i = 0;
if (!m.isConstructor) {
......@@ -1448,6 +1534,9 @@ public class JavaParser {
}
for (ArrayList<MethodObj> list : c.methods.values()) {
for (MethodObj m : list) {
if (m.isIgnore) {
continue;
}
out.print(m.returnType + " " + toC(c.className) + "_" + m.name + "(");
int i = 0;
if (!m.isStatic && !m.isConstructor) {
......
......@@ -13,66 +13,93 @@ import java.util.ArrayList;
*/
public interface Statement {
boolean isEnd();
// toString
}
/**
* The base class for statements.
*/
abstract class StatementBase implements Statement {
public boolean isEnd() {
return false;
}
}
/**
* A "return" statement.
*/
class ReturnStatement implements Statement {
class ReturnStatement extends StatementBase {
Expr expr;
public String toString() {
return "return " + (expr == null ? "" : expr) + ";";
}
}
/**
* A "do .. while" statement.
*/
class DoWhileStatement implements Statement {
class DoWhileStatement extends StatementBase {
Expr condition;
Statement block;
public String toString() {
return "do {\n" + block + "} while (" + condition + ");";
}
}
/**
* A "continue" statement.
*/
class ContinueStatement implements Statement {
class ContinueStatement extends StatementBase {
public String toString() {
return "continue;";
}
}
/**
* A "break" statement.
*/
class BreakStatement implements Statement {
class BreakStatement extends StatementBase {
public String toString() {
return "break;";
}
}
/**
* An empty statement.
*/
class EmptyStatement implements Statement {
class EmptyStatement extends StatementBase {
public String toString() {
return ";";
}
}
/**
* A "switch" statement.
*/
class SwitchStatement implements Statement {
class SwitchStatement extends StatementBase {
Expr expr;
StatementBlock defaultBlock;
ArrayList<Expr> cases = new ArrayList<Expr>();
ArrayList<StatementBlock> blocks = new ArrayList<StatementBlock>();
public String toString() {
StringBuilder buff = new StringBuilder();
buff.append("switch (").append(expr).append(") {\n");
......@@ -87,38 +114,47 @@ class SwitchStatement implements Statement {
buff.append("}");
return buff.toString();
}
}
/**
* An expression statement.
*/
class ExprStatement implements Statement {
class ExprStatement extends StatementBase {
Expr expr;
public String toString() {
return expr + ";";
}
}
/**
* A "while" statement.
*/
class WhileStatement implements Statement {
class WhileStatement extends StatementBase {
Expr condition;
Statement block;
public String toString() {
String w = "while (" + condition + ")";
String s = block.toString();
return w + "\n" + s;
}
}
/**
* An "if" statement.
*/
class IfStatement implements Statement {
class IfStatement extends StatementBase {
Expr condition;
Statement block;
Statement elseBlock;
public String toString() {
String w = "if (" + condition + ") {\n";
String s = block.toString();
......@@ -127,12 +163,14 @@ class IfStatement implements Statement {
}
return w + s + "}";
}
}
/**
* A "for" statement.
*/
class ForStatement implements Statement {
class ForStatement extends StatementBase {
Statement init;
Expr condition;
Expr update;
......@@ -141,6 +179,7 @@ class ForStatement implements Statement {
Type iterableType;
String iterableVariable;
Expr iterable;
public String toString() {
StringBuffer buff = new StringBuffer();
buff.append("for (");
......@@ -174,54 +213,81 @@ class ForStatement implements Statement {
}
return buff.toString();
}
}
/**
* A statement block.
*/
class StatementBlock implements Statement {
class StatementBlock extends StatementBase {
ArrayList<Statement> instructions = new ArrayList<Statement>();
public String toString() {
StringBuilder buff = new StringBuilder();
for (Statement s : instructions) {
if (s.isEnd()) {
break;
}
buff.append(JavaParser.indent(s.toString()));
}
return buff.toString();
}
}
/**
* A variable declaration.
*/
class VarDecStatement implements Statement {
class VarDecStatement extends StatementBase {
Type type;
ArrayList<String> variables = new ArrayList<String>();
ArrayList<Expr> values = new ArrayList<Expr>();
public String toString() {
StringBuilder buff = new StringBuilder();
buff.append(type).append(' ');
StringBuilder assign = new StringBuilder();
for (int i = 0; i < variables.size(); i++) {
if (i > 0) {
buff.append(", ");
}
buff.append(variables.get(i));
String varName = variables.get(i);
buff.append(varName);
Expr value = values.get(i);
if (value != null) {
if (value.getType().isSimplePrimitive()) {
buff.append(" = ").append(value);
} else {
assign.append(varName).append(" = reference(").append(value).append(");\n");
}
}
}
buff.append(";");
if (assign.length() > 0) {
buff.append("\n");
buff.append(assign);
}
return buff.toString();
}
}
/**
* A native statement.
*/
class StatementNative implements Statement {
class StatementNative extends StatementBase {
String code;
public String toString() {
return code;
}
public boolean isEnd() {
return code.equals("return;");
}
}
......@@ -26,10 +26,14 @@ public class Test extends TestBase {
}
public void test() throws IOException {
// gcc --std=c99 test.c
// gcc --std=c99 -o test test.cpp
// chmod +x test
// ./test
// (for "mixed declarations and code")
// not supported yet:
// exceptions
// HexadecimalFloatingPointLiteral
// int x()[] { return null; }
// annotations
......
......@@ -25,7 +25,11 @@ int main(int argc, char** argv) {
* @param args the command line arguments
*/
public static void main(String... args) {
System.out.println("Hello " + "World" + 1);
for (int i = 0; i < 10; i++) {
String s = "Hello " + i;
System.out.println(s);
s = null;
}
}
}
......@@ -11,6 +11,10 @@ package org.h2.java.lang;
*/
public class Integer {
public static final int MIN_VALUE = 1 << 31;
public static final int MAX_VALUE = (int) ((1L << 31) - 1);
/**
* Convert a value to a String.
*
......@@ -21,7 +25,32 @@ public class Integer {
// c: char ch[20];
// c: snprintf(ch, 20, "%d", x);
// c: return string(ch);
return null;
// c: return;
if (x == MIN_VALUE) {
return String.wrap("-2147483648");
}
char[] ch = new char[20];
int i = 20 - 1, count = 0;
boolean negative;
if (x < 0) {
negative = true;
x = -x;
} else {
negative = false;
}
for (; i >= 0; i--) {
ch[i] = (char) ('0' + (x % 10));
x /= 10;
count++;
if (x == 0) {
break;
}
}
if (negative) {
ch[--i] = '-';
count++;
}
return new String(ch, i, count);
}
}
......@@ -6,6 +6,8 @@
*/
package org.h2.java.lang;
import org.h2.java.Ignore;
/* c:
#include <stdlib.h>
......@@ -38,16 +40,24 @@ package org.h2.java.lang;
void* new_array(jint object, jint size, jint length);
void* new_object(jint type, jint size);
void* set_object(void** target, void* o);
void* reference(void* o);
void release(void* o);
void* set(void* o, void* n);
void* string(char* s);
*/
/*
* Object layout:
* m-3: arrays: length; otherwise not allocated
* m-2: arrays: 0; otherwise type
* m-2: data type
* m-1: number of references
* m: object data
*
* Array layout:
* m-3: length (number of elements)
* m-2: 0 (array marker)
* m-1: number of references
* m: first element
*/
/**
......@@ -57,25 +67,57 @@ public class String {
/* c:
void* new_array(jint object, jint size, jint length) {
int count = sizeof(jint) * 3 + size * length;
int* m = (jint*) calloc(1, count);
void* new_array_with_count(jint object, jint size, jint length, jint refCount) {
jint count = sizeof(jint) * 3 + size * length;
jint* m = (jint*) calloc(1, count);
*m = length;
*(m + 2) = 1;
*(m + 2) = refCount;
return m + 3;
}
void* new_object(jint type, jint size) {
int count = sizeof(jint) * 2 + size;
int* m = (jint*) calloc(1, count);
void* new_array(jint object, jint size, jint length) {
return new_array_with_count(object, size, length, 1);
}
void* new_static_array(jint object, jint size, jint length) {
return new_array_with_count(object, size, length, 0);
}
void* new_object_with_count(jint type, jint size, jint refCount) {
jint count = sizeof(jint) * 2 + size;
jint* m = (jint*) calloc(1, count);
*m = type;
*(m + 1) = 1;
*(m + 1) = refCount;
return m + 2;
}
void* set_object(void** target, void* o) {
int* m = (jint*) target;
if (*(m - 1) == 1) {
void* new_object(jint type, jint size) {
return new_object_with_count(type, size, 1);
}
void* new_static_object(jint type, jint size) {
return new_object_with_count(type, size, 0);
}
void* reference(void* o) {
if (o != 0) {
jint* m = (jint*) o;
if (*(m - 1) > 0) {
(*(m - 1))++;
}
}
return o;
}
void release(void* o) {
if (o == 0) {
return;
}
jint* m = (jint*) o;
if (*(m - 1) <= 1) {
if (*(m - 1) == 0) {
return;
}
if (*(m - 2) == 0) {
free(m - 3);
} else {
......@@ -84,16 +126,15 @@ void* set_object(void** target, void* o) {
} else {
(*(m - 1))--;
}
*target = o;
m = (jint*) target;
if (o != 0) {
(*(m - 1))++;
}
return m;
}
void* set(void* o, void* n) {
release(o);
return reference(n);
}
void* string(char* s) {
int len = strlen(s);
jint len = strlen(s);
jchar* chars = NEW_ARRAY(sizeof(jchar), len);
for (int i = 0; i < len; i++) {
chars[i] = s[i];
......@@ -144,4 +185,14 @@ void* string(char* s) {
return chars.length;
}
@Ignore
public java.lang.String asString() {
return new java.lang.String(chars);
}
@Ignore
public static String wrap(java.lang.String x) {
return new String(x.toCharArray());
}
}
......@@ -33,6 +33,8 @@ public class System {
memmove(((jchar*)dest) + destPos,
((jchar*)src) + srcPos, sizeof(jchar) * length);
*/
// c: return;
java.lang.System.arraycopy(src, srcPos, dest, destPos, length);
}
/**
......@@ -50,7 +52,8 @@ public class System {
memmove(((jbyte*)dest) + destPos,
((jbyte*)src) + srcPos, sizeof(jbyte) * length);
*/
// c: return;
java.lang.System.arraycopy(src, srcPos, dest, destPos, length);
}
}
......@@ -18,7 +18,7 @@ public class Arrays {
* @param x the value
*/
public static void fill(char[] array, char x) {
for (int i = 0; i < array.length; i++) {
for (int i = 0, size = array.length; i < size; i++) {
array[i] = x;
}
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论