最近因业务关系,开始正儿八经的学java。因为C的背景,先入为主, 就和C做比较学习。
/*Struct.java -- how C to java * OO 的四大要素: 抽象,封装,模块化,分层 * Java 的优点: * 安全性: * 1. 引用必须初始化; * 2. 数组下标检查; * 3. 死机时优雅的打印StackTrace。 * 其他优点以后涉及到时再说。 * * author: ludi 2014.03*/ import java.lang.System; /*目录分层结构,C中没有语法上的支持*/ class Type{/*C中的Struct抽象封装*/ public int a, b; public void change(){/*C++中的Struct*/ this.a += 1; this.b += 2; } } public class Struct{/*必须和文件名一样: 编译器强制模块化*/ static void change(Type t){/*跟对象实例无关的函数必须是static*/ t.a += 1; /*C++中的引用传递*/ t.b += 2; /*如何打印引用的内存地址?*/ int[] x = {1,2,3,4}; /*数组定义比C中的int[4],类型更具有一致性*/ Type[] y = {null, null, null}; /*y数组是在堆上分配么?如何释放?*/ } public static void main(String[] args){ Type t = new Type(); /*编译器强制引用必须初始化*/ //System.printf("a = %d b = %d\n", t.a, t.b); /**/ System.out.println(t.a + " " + t.b); /*安全的打印*/ change(t); /*引用就是指针*/ t.change(); /*提倡这样用才是OO style*/ System.out.println(t.a + " " + t.b); } }
以前跟风别人说java语法比较啰嗦,特别是看了某些一上来就写莫某设计模式的时候。现在看来是写代码的人没有做好抽象这一步了。当然非要看hello world 最短, C也比不上perl之类的。
从实用主义的观点,给第一个应用例子, RSA加密和解密:
/*RSA.java -- using RSA do encryption and decryption * java 优点: * 有标准的包:BigInteger * * author: ludi 2014.03 * */ import java.math.*; import java.util.*; public class RSA{ public static BigInteger relativePrime(BigInteger t) {/*return number k, such that gcd(k,t) = 1.*/ BigInteger k = null; Random rnd = new Random(); do{ k = new BigInteger(64, rnd); /*generate a random k \in (0, 2^64)*/ }while(!t.gcd(k).equals(BigInteger.ONE)); return k; } public static void main(String[] args){ if(args.length < 1){ System.out.println("usage: RSA message\n"); return; } Random rnd = new Random(); BigInteger p = null, q = null, n = null, t = null, e = null, d = null, one = BigInteger.ONE, raw = null, encrypted = null, decrypted = null; String msg = null; p = BigInteger.probablePrime(128, rnd); /*bit length = 128*/ q = BigInteger.probablePrime(128, rnd); n = p.multiply(q); t = (p.subtract(one)).multiply(q.subtract(one)); e = relativePrime(t); d = e.modInverse(t); raw = new BigInteger(args[0].getBytes());/*bit stream*/ encrypted = raw.modPow(e, n); decrypted = encrypted.modPow(d, n); //System.out.println("raw integer: " + raw // + "\np = " + p + "\nq = " + q); System.out.println("raw message: '" + args[0] + "'"); msg = new String(encrypted.toByteArray()); System.out.println("encrypted: '" + msg + "'"); msg = new String(decrypted.toByteArray()); System.out.println("decrypted: '" + msg + "'"); System.out.println("public key = (n,e), private key = (n,d)"); System.out.println("n = " + n); System.out.println("e = " + e); System.out.println("d = " + d); } } /* ludi@ubun:~ $ java RSA 'Pay $123.45' raw message: 'Pay $123.45' encrypted: 'E�����xs>�����-W�Gå�r蕎��h]' decrypted: 'Pay $123.45' public key = (n,e), private key = (n,d) n = 49501839457986030455953244525444742182049040819775728995411857641724770216969 e = 772464604889112363 d = 5561519969026911507015137142430098280107716226986092378589977153350026908067 ludi@ubun:~ $ 由于是随机的,每次运行的n,e,d可能都不同。 p,q,k 的长度取多少合适? RSA 定理: 设 n = p * q, t = (p - 1)*(q - 1), e 与t 互素,1 = e*d(mod t), 则 对于任何0 < a < n, 有a = a^(e*d) (mod n)。 代码中的n长度 = 128+128-1 = 255。如果输入"12", 则a = 0x3132。 即一个字符对应到8bit长,因此输入字符串长度应当小于 255/8 = 36。 e限定到64bit,应该是可以的(定理?)。通常是服务器生成密钥, 把公钥(n,e)发给客户端,客户端加密,较小的e使得客户端运算量小些。 */
后续打算继续贴上,我学习java版的数据结构方面的。