package hello; public class FirstSample { public static void main(String[]args) { System.out.println("Hello World!"); } }
源代码的文件名必须与公共类的文件名相同。
main方法必须声明为public
如果希望在终止程序时返回其他代码, 需要调用System.exit方法。
C#中文件注释为///, java中文件注释为以/**开始, */结束。
int, short, long, byte(1字节)
前缀加上0b可表示二进制数
float, double
有三个表示出错的浮点数值:
不能用如下语句判断:
if (x == Double.NaN)
所有非数值的值都认为是不相等的
可以使用
if (Double.isNaN(x))
java中char类型描述了UTF-16编码中的一个代码单元(code unit)
只有true, false两个值
在c++中, int i = 10 是一个定义
而 extern int i 是一个声明
java中不区分声明和定义
java中用关键词final指示常量
对于浮点运算, 可在方法之前使用strictfp关键字标记, 使其使用严格的浮点运算
public static strictfp void main(String args[])
Math类中可以调用各种数学函数
public class FirstSample { public static void main(String[]args) { double x = 4; double y = Math.sqrt(x); System.out.println(y); } }
floorMod解决了负数取余的问题.
floorMod(position + adjustment, 12)(对于负除数, floorMod仍会得到负数结果)
Math.sin
Math.cos
Math.tan
Math.atan
Math.atan2
Math.exp
Math.log
Math.log10
Math.PI
Math.E
对于这些默认定义的类, 可以使用静态引入
import static java.lang.Math.*;
import static java.lang.Math.*; public class FirstSample { public static void main(String[]args) { double x = 4; double y = sqrt(x); System.out.println(y); } }
Math类中, 所有的方法都使用计算机浮点单元中的例程, 如果得到一个准确的结果更重要, 那么应该使用StrictMath类, 使用fdlibm实现算法, 以确保在所有平台得到相同的结果。
int转换成double类型不会损失精度
double x= 9.997; int nx = (int)x;
对浮点数进行舍入运算用Math.round方法
double x = 9.997; int nx = (int) Math.round(x);
round方法返回的结果是long类型, 仍需要强制类型转换
运算符>>>会用0填充高位, 而>> 会用符号位填充高位
enum Size {SMALL, MEDIUM, LARGE, EXTRA_LARGE}; Size t = Size.MEDIUM;
String e = ""; //an empty string String greeting = "Hello";
String类中的substring方法可以从一个较大的字符串中提取出来一个子串
String greeting = "Hello"; String s = greeting.substring(0, 3);
创建s为由字符“Hel”组成的字符串。
java允许使用+号进行字符串的拼接。
String类中没有提供修改字符串的方法, java文档中称String类对象为不可变字符串, 不过可以通过修改字符串变量, 使其引用其它字符串。
greeting = greeting.substring(0, 3) + "p!";
java中字符串相当于char* 指针.
使用equals方法
s.equals(t)
相等返回true, 否则返回false
java中的compareTo则完全与C中的strcmp类似
if (greeting.compareTo("Hello") == 0)...
空串是长度为0的字符串, 可调用如下代码进行检查
if (str.length() == 0) 或 if (str.equals(""))
null串表示目前没有任何对象与该变量关联
判断使用如下代码:
is(str == null)
大多数常用Unicode字符使用一个代码单元就可以表示, 而辅助单元需要一对代码单元
实际的码点数量可以调用
String greeting = "Hello"; int cpCount = greeting.codePointCount(0, greeting, length());
调用s.charAt(n)将返回位置n的代码单元
char first = greeting.charAt(0); char last = greeting.charAt(4);
要想得到第i个码点
int index = greeting.offsetByCodePoints(0, i); // 偏移i个码点 int cp = greeting.codePointAt(index);
该字符需要两个代码单元, 调用charAt()时请注意
如果想遍历一个字符串, 并依次查看每一个码点, 可使用如下代码
int cp = sentence.codePointAt(i); if(Character.isSupplementaryCodePoing(cp)) i += 2; else i++;
使用如下语句实现回退操作:
i--; if (character.isSurrogate(sentence.charAt(i))) i--; int cp = sentence.codePointAt(i);
更容易的方法是使用codePoints方法, 其生成一个int值的“流”, 每个int对应一个码点, 可以将其转换为一个数组, 再完成遍历。
int [] codePoints = str.codePoints().toArray();
反之, 可以使用构造函数
String str = new String(codePoints, 0, codePoints.length);
使用StringBuilder类可以用多个较短字符串来构建字符串
StringBuilder builder = new StringBuilder(); builder.append(ch); builder.append(str); String completedString = builder.toString();
StringBuffer和StringBuilder的API是相同的, 但StringBuffer支持多线程, 效率稍低。
首先需要构建一个Scanner对象, 并与System.in关联
Scanner in = new Scanner(System.in);
System.out.print("What is your name?"); String name = in.nextLine();
nextLine方法可以实现C中gets函数的效果。
要想读取一个整数, 则调用nextInt方法
System.out.print("How old are you?"); int age = in.nextInt();
要想读取浮点数, 则使用nextDouble方法。
Scaner类定义在java。util包中, 当时用的类不是定义在java.lang包中时, 必须使用import
import java.util.*; public class InputTest { public static void main(String[] args) { Scanner in = new Scanner(System.in); // get first input System.out.print("What is your name?"); String name = in.nextLine(); //get second input System.out.print("How old are you?"); int age = in.nextInt(); System.out.println("Hello" + name + ". Next you will be " + (age + 1)); } }
Console类实现了从控制台读取密码
import java.io.Console.*; Console cons = System.console(); String username = cons.readLine("User name:"); char[] passwd = cons.readPasswword("Password:");
可以使用静态的String。format方法创建一个格式化的字符串, 而不打印输出
String message = String.format("Hello, %s . Next you will be %d", name, age);
System.out.printf("%1$s %2$tB %2$te, %2$tY","Due Date:" , new Date());
还可以使用< 标志
System.out.printf("%s %tB %<te, %<tY","Due Date:" , new Date());
若想进行读取需要用一个File对象构造一个Scanner对象
Scanner in = new Scanner(Path.get("myfile.txt"), "UTF-8");
要想写入文件, 需要构造PrintWrite对象, 在构造器中, 只需要提供文件名
PrintWriter out = new PrintWriter("myfile.txt", "UTF-8");
完成之后记得关闭文件流, 不然不会保存写入内容
out.close();
如果用一个不存在的文件构造Scanner, 或者用一个不能被创建的文件名构造一个PrintWriter, 那么就会发生异常, 这需要在main方法中用子句throws标记
public static void main(String[] args) throws IOException { Scanner in = new Scanner(Paths.get("myfile.txt"), "UTF-8"); ... }
与C语言不同, 不能在嵌套的块中声明同名变量
import java.util.*; /** * This program demonstrates a <code>while<code> loop. * @author Cay Horstmann *@writeby Saigyoujinexas */ public class Retirement { public static void main(String[] args) { //read inputs Scanner in = new Scanner(System.in); System.out.print("How much money do you need to retire?"); double goal = in.nextDouble(); System.out.print("How much money will you contribute every year?"); double payment = in.nextDouble(); System.out.print("Interest rate in %:"); double interestRate = in.nextDouble(); double balance = 0; int years = 0; //update account balance while goal is not reached while (balance < goal) { //add this year's payment and interest balance += payment; double interest = balance * interestRate / 100; balance += interest; years++; } System.out.println("You can retire in " + years + " years."); } }
import java.util.*; /** * This program demonstrates a <code>while<code> loop. * @author Cay Horstmann *@writeby Saigyoujinexas */ public class Retirement2 { public static void main(String[] args) { //read inputs Scanner in = new Scanner(System.in); System.out.print("How much money will you contribute every year?"); double payment = in.nextDouble(); System.out.print("Interest rate in %:"); double interestRate = in.nextDouble(); double balance = 0; int year = 0; String input; //update account balance while goal is not reached do { //add this year's payment and interest balance += payment; double interest = balance * interestRate / 100; balance += interest; year++; //print current balance System.out.printf("After year %d, your balance is %,.2f%n", year, balance); // ask if ready to retire and get input System.out.print("Ready to retire?(Y / N)"); input = in.next(); }while(input.equals("N")); } }
对于switch循环, 必须有break语句
如果故意使用直通式(fallthrough)行为
在其外围方法加个标注 @SuppressWarnings(“fallthrough”)
java提供了一种** 带标签的break语句**
Scanner in = new Scanner(system.in); int n; read_data: while(...) { for(...) { System.out.print("Enter a number >= 0"); n = in.nextInt(); if(n < 0) // should never happen-can't go on break read_data; //break out of read_data loop ... } } // this statement is excuted immediately after the labeld break if (n < 0) // check for bad situation { //deal with bad situation } else { //carry out normal processing }
该标签可以应用到任何语句, 甚至是if语句或块语句中
label: { ... if (condition) break label; // exit block }
continue语句同样可带标签, 将跳转到与标签匹配的循环首部
java中两个很有用的类:BigInteger和Bigdecimal。
使用静态的valueOf方法可以将普通数值转换为大数值。
BigInteger a = BigInteger.valueOf(100);
不能使用运算符对大数值进行运算
需要使用add和multiply方法
BigInteger c = a.add(b); BigInteger d = c.multiply(b.add(BigInteger.valueOf(2)));
java不提供运算符重载功能
import java.math.*; import java.util.*; /** * This program uses big numbers to compute the odds of winning the grand prize in a lottery. * @author Cay Horstmann */ public class BigIntegerTest { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("How many numbers do you need to draw?"); int k = in.nextInt(); System.out.print("What is the highest number you can draw? "); int n = in.nextInt(); /* *compute binomial coeffcient n*(n - 1)*(n-2)*(n-3)*...*(n-k+1)/(1*2*3*4*...*k) */ BigInteger lotteryOdds = BigInteger.valueOf(1); for (int i = 1; i <= k; i++) { lotteryOdds = (lotteryOdds.multiply(BigInteger.valueOf(n - i + 1)).divide(BigInteger.valueOf(i))); System.out.println(lotteryOdds); } System.out.println("Your odds are 1 in " + lotteryOdds + ". Good luck!"); } }
int a[];
该语句仅声明了变量还需要初始化
int [] a = new int[100];
创建字符数组时所有元素初始化为0。
获得数组元素数量可以使用array.length.
for (int i = 0; i < a.length; i++) System.out.println(a[i]);
for (variable: collection) statement
定义一个变量用于暂存集合中的每一个元素并执行相应的语句
collection集合表达式必须是一个数组或者是一个实现了Iterable接口的类对象
for (int element: a) System.out.println(element);
等价于
for (int i = 0; i < a.length; i++) System.oout.println(a[i]);
但是for each 循环更为简洁
有个更简单的方式打印一个集合的所有元素, 即使用Arrays类中的toString 方法, 返回被放置在方括号内的数组元素, 用逗号分隔。
System.out.println(Arrays.toString(a));
int [] smallPrimes = {2, 3, 5, 7, 11, 13 };
甚至可以申请初始化一个匿名的数组
new int[] {17, 19, 23, 29, 31, 37 }
使用这种语法可以重新初始化一个数组
smallPrimes = new int[] {17, 19, 23, 29, 31, 37 };
此时两个变量**引用 **同一个数组
int [] luckNumbers = smallPrimes; luckNumber[5] = 12 // now smallPrimes[5] is also 12
如果希望是进行拷贝而不是引用同一个数组, 使用Arrays类的copyOf方法
int [] copiedLuckNumbers = Arrays.copyOf(luckNumbers, 2 * luckNumbers.length);
第二个参数是新数组的长度, 故该方法可以用来增加数组长度
luckNumbers = Arrays.copyOf(luckNumbers, 2 * luckNumbers.length);
java基本上与C++分配在堆上的数组指针一致
public class Message { public static void main(String[] args) { if (args.length == 0 || args[0].equals("-h")) System.out.print("Hello,"); else if (args[0].equals("-g")) System.out.print("Goodbye."); for (int i = 1; i < args.length; i++) System.out.print(" " + args[i]); System.out.println("!"); } }
在java程序中, 程序名不存在args数组中
数值型数组使用Arrays类中的sort方法
int [] a= new int[1000]; ... Arrays.sort(a)
该方法使用优化的快速排序算法
import java.util.*; /** * This program demonstrates array manipulation. * @author Cay Horstmann */ public class LotteryDrawing { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("How many numbers do you need to draw? "); int k = in.nextInt(); System.out.print("What is the highest number you can draw? "); int n = in.nextInt(); //file an array with number 1, 2, 3, 4, ... int [] numbers = new int[n]; for (int i = 0; i < numbers.length; i++) numbers[i] = i + 1; //draw k numbers and put them into a second array int[] result = new int[k]; for (int i = 0; i < result.length; i++) { //make random index between 0 and n - 1 int r = (int) (Math.random() * n); // pick the element at the random location result[i] = numbers[r]; //move the last element into the random location numbers[r] = numbers[n - 1]; n--; } // print the sorted array Arrays.sort(result); System.out.println("Bet the following combination. It will make you rich!"); for (int r: result) System.out.println(r); } }
Math.random方法将生成一个0到1的浮点数。
double [][] balances;
同样, 在初始化完成后才能使用
balances = new double[NYEARS][NRATES]
int magicSquare = { {16, 3, 2, 13}, {5, 10, 11, 8}, {9, 6, 7, 12}, {4, 15, 14, 1} };
for each 循环不能自动处理二维数组每个元素
for (double[] row: a) for (double value: row) do something with value
要想快速打印一个二维数组, 可以调用
System.out.println(Arrays.deepToString(a));
/** * This program shows how to store tabular data in a 2D array. * @author Cay Horstmann */ public class CompoundInterest { public static void main(String[] args) { final double STARTRATE = 10; final int NRATES = 6; final int NYEARS = 10; //set interest rates to 10.....15% double[] interestRate = new double[NRATES]; for (int j = 0; j < interestRate.length; j++) interestRate[j] = (STARTRATE + j) / 100.0; double [][] balances = new double[NYEARS][NRATES]; //set initial balances to 10000 for (int j = 0; j < balances[0].length; j++) balances[0][j] = 10000; //compute interest for future years for (int i = 1; i < balances.length; i++) { for (int j = 0; j < balances[i].length; j++) { //get last year's balances from previous now double oldBalance = balances[i - 1][j]; //compute interest double interest = oldBalance * interestRate[j]; //compute this year's balances balances[i][j] = oldBalance + interest; } } //print one row of interest rates for (int j = 0; j < interestRate.length; j++) System.out.printf("%9.0f%%", 100 * interestRate[j]); System.out.println(); //print balance table for (double[] row: balances) { for (double b: row) System.out.printf("%10.2f", b); System.out.println(); } } }
java实际上没有多维数组, 多维数组被解释为数组的数组
int[][] odds = new int[NMAX + 1][]; for (int n = 0; n <= NMAX; n++) odds[n] = new int[n + 1];
分配数组后, 就可以采用通常的方式进行访问
for (int n = 0; n < odds.length; n++) for (int k = 0; k < odds[i].length; k++) { //compute lotteryOdds; ... odds[n][k] = lotteryOdds; }
double[][] balances = new double[10][6];
该声明等同于C++中
double** balances = new double*[10]; for (int i = 0; i < 10; i++) balances[i] = new double[6];
杨辉三角打印
/** * This program demostrates a triangular array. * @author Cay Horstmann */ public class lotteryArray { public static void main(String[] args) { final int NMAX = 10; //allocate triangular array int[][] odds = new int[NMAX + 1][]; for (int n = 0; n <= NMAX; n++) odds[n] = new int[n + 1]; //fill triangular array for(int n = 0; n < odds.length; n++) for(int k = 0; k < odds[n].length; k++) { /* *compute binomial coefficient n*(n-1)*(n-2)*...*(n-k+1)/(1*2*3*...*k) */ int lotteryOdds = 1; for (int i = 1; i <= k; i++) lotteryOdds = lotteryOdds * (n-i + 1) / i; odds[n][k] = lotteryOdds; } //print triangular array for (int[] row: odds) { for (int odd : row) System.out.printf("%4d", odd); System.out.println(); } } }
算法优化:
/** * This program demostrates a triangular array. * @author Cay Horstmann */ public class lotteryArray { public static void main(String[] args) { final int NMAX = 10; //allocate triangular array int[][] odds = new int[NMAX + 1][]; for (int n = 0; n <= NMAX; n++) { odds[n] = new int[n + 1]; odds[n][0] = 1; odds[n][n] = 1; } //fill triangular array for(int n = 1; n < odds.length; n++) for(int k = 1; k < odds[n].length - 1; k++) odds[n][k] = odds[n - 1][k - 1] + odds[n - 1][k]; //print triangular array for (int[] row: odds) { for (int odd : row) System.out.printf("%4d", odd); System.out.println(); } } }