01.java基本设计结构
01.java基本设计结构
1.1 注释
java提供三种注释方式,即:
//这是一个注释
/*这是一个注释*/
/**
* 这是一个注释
*/1.2 数据类型
基本类型和对象引用在栈,对象在堆
1.2.1 基本数据类型
整型:表示无小数部分的数,允许是负数
- 未定义的数字默认为int,想要转化为其他类型需在数字前使用 (其他类型) 转化,例:
byte a = (byte) 1; - 另外,对于长数字,java现在允许在数字字面量中使用
_分隔,例:1_000_000_000 - 如果想要快速生成或说明长整型可以在数字后添加L(大小写均可)声明
- java中没有无符号数,但可以将有符号数当成无符号数,使用对应整型类的.toUnsignedInt()函数当成无符号数处理,再转换回来,极不常用
类型 存储需求(字节) 取值范围 int 4 -21.475亿左右,21.475亿左右 short 2 -32768,32767 long 8 -9e+18,9e+18 byte 1 -128,127 - 未定义的数字默认为int,想要转化为其他类型需在数字前使用 (其他类型) 转化,例:
浮点类型:表示有小数点的数据类型
- java中浮点数精度不高,很可能无法用来进行==判断,更无法进行不接受舍入的运算
- 含小数的数默认为double,可以在后面加f进行转换
- 存在三种特殊的小数,正无穷、负无穷、NaN(不是一个数字),例如:正数/0得到正无穷,0/0得到NaN,常量
Double.POSITIVE_INFINITY,Double.NEGATIVE_INFINITY和Double.NaN(与相应的Float类型的常量一样)分别表示这三个特殊的值 - 特别要说明的是,不能这样检测一个特定的值是否等于
Double.NaN:
if(x == Double.NaN) //is never true
//所有“非数值”的值都认为是不同的。
//然而,可以使用Double.isNaN方法:
if(Double.isNaN(x)) //check whether x is "not a number"| 类型 | 存储需求(字节) | 取值范围 |
|---|---|---|
| float | 4 | ±3.4e+38F(有效位数6~7位) |
| double | 8 | ±1.79e+308(有效位数15位) |
char类型:表示单个字符(一个char值),一些Unicode字符(两个char值)- 无论是一个还是两个值存储的字符,都是一个代码单元,除非必要不建议使用char处理字符串的代码单元
- Unicode值可以是使用\u000到\ufff转义得到的字符,这些字符会在运行前进行转义(无论在哪),慎重使用转义\u字符
数据类型转换:可自动转换,也可以使用强制类型转换(其他类型) 数值转换成其他基本类型数值
- 自动转换:从低级到高级自动转换,整数类型可以自动转化为浮点类型,可能会产生舍入误差

自动转换 - 强制转换:格式为(要转成类型)变量名,可能会溢出
boolen类型:有两个值:
false和true,整数和布尔类型不能转换,不会遇到布尔类型与0比较的情况出现
1.2.2 常量
使用final声明的数据类型被称为常量,只能被赋值一次
1.2.3 自定义枚举类型
- 对于需要存放特定有限数据的类型可设定为枚举类型
enum,例如:
enum Size { SMALL,MEDIUM,LARGE,EXTRA_LARGE};
/*使用方法,声明该类型的变量,只能存储以上类型值或不存值为null*/
Size s = Size.SMALL;1.2.4 字符串
字符串是标准java类库提供的一个预定义类,叫做
String,每个用双引号括起来的字符串都是String的一个实例由于String是不可变(immmutable)字符串,java没有提供修改字符串中某个字符的方法
String类型有50多种方法,通过变量名.方法名调用
String字符串不能通过
==判断是否相同,==只能判断存放地址是否一致,要通过.equals(String other)判断,如果相等,返回true,否则返回false补充Unicode内容:unicode内容
- Unicode标准中,码点与字符并不一定总是一一对应的,在Unicode标准中,一个字符有可能有多个码点,比如U+51C9与U+F977都是同一个字符“凉”,这主要是为了兼容韩国字符集的标准。
- 也有可能由多个码点来表示一个字符,最常见的就是组合字符,字符
g̈是由基本字符U+0067和U+0308(这个字符称为组合字符)组合而成,虽然以上字符是由两个Unicode码点组成,但现实中,人们会认为这是一个字符。以上由两个码点组合而成的字符称为“用户感知字符”(这是Unicode对字符的一种理解方法)。 - 也就是说,一个可视的代码单元可能由两个码点构成,因此尽量不要调用码点(
.codePointAt方法),它的总长度和字符串的总长度可能不一致 - 在这种表示法中,补充字符表示为一对字符值,第一个字符来自高代理项范围(
\uD800-\uDBFF),第二个字符来自低代理项范围(\uDC00-\uDFFF)
下面提供部分String中的方法:
String a = "123"; //String a = new String(char[])使用字符数组转换 //转换类 char[] b = a.toCharArray();//将字符串转化为字符(代码单元)数组 //相关信息类 a.charAt(0);//获得一个代码单元,相当于a[0] a.codePointAt(0);//获得对应码点的值(尽量不要用,得到的是对应的十进制数字,例ASCII码) a.length();//返回字符串长度 a.substring(0,2);//同python:a[0:2] String newStr = a.substring(0,1) + "new";//通过+号连接字符串进行拼接修改字符串 //判断类 a.blank();//由空格组成返回true a.empty();//为空返回true a.equals(newStr);//两串相等返回true a.equalsIgnoreCase(newStr);//忽略大小写是否相等,相等返回true a.startsWith("1");a.endsWith("3");//a以1开头、以3结尾分别返回true //实用类 a.indexOf(newStr,1);//查找从第1个位置开始出现的第一个newStr子串的位置(第一个字母下标),不存在返回-1 a.lastIndexOf(newStr,1);//查找最后出现的位置,其余同indexOf(string,int) a.replace("1",newStr);//用newStr(可为StringBulider类的变量)代替a字符串中的所有"1"返回一个新的字符串 a.join(",", "12", new StringBuilder("C"), new StringBuffer("D"), a);//用","分隔连接所有元素,返回一个新字符串 a.strip();//删除a两端的空格 a.trim();//删除a两端小于(U+0020)的字符 a.repeat(2);//返回一个字符串,该字符串重复a字符串2次 a.toLowerCase();//返回一个新字符串,将a中大写改小写 a.toUpperCase();//返回一个新字符串,将a中小写改大写StringBuffer类: 如果需要用许多小段的字符串构建一个字符串, 那么应该按照下列步骤进行
首先, 构建一个空的字符串构建器:
StringBuilder builder = new StringBuilder();当每次需要添加一部分内容时, 就调用 append 方法。
builder.append(ch); // appends a single characterbui1der.append(str); // appends a string在需要构建字符串时就凋用 toString 方法, 将可以得到一个
String对象, 其中包含了构建器中的字符序列。String completedString = builder.toString();其他方法:
- void setCharAt(int i ,char c)将第
i个代码单元设置为c - StringBuilder insert(int offset,String str)在
offset位置插入一个字符串并返回this - StringBuilder insert(int offset,Char c)在
offset位置插入一个代码单元并返回this - StringBuilder delete(int startindex,int endlndex)删除偏移量从
startindex到-endlndex-1的代码单元并返回this
- void setCharAt(int i ,char c)将第
1.3 运算
1.3.1 基本运算
+-*/符合数学,参与/运算的数都是整数时为整数除法(同C++向下取整),存在浮点数时为浮点除法,取余也与C++相同,+-得到的结果为取值范围较大的类型特殊数学运算和科学中数值在Math类中
结合运算
+=-=*=/=%=,无+、-直接使用会发生类型转换的问题关系运算
!===等,与C++基本相同逻辑运算
&&||!与或非沿用了C++的短路方式,如果最后结果已知,第二个操作就不必进行了,可通过这种机制避免越界等错误(先判断是否可能触发错误,再执行操作),如果希望所有操作全部执行可以使用&|(非短路)自增自减
++--,同C++,相当于+=1-=1三元运算
condition ? expression1 : expression2当condition为真时,返回expression1,否则返回expression2位运算
&("and")|("or")^("xor")~("not")使用二进制对数字运算,另外还有<<>>将二进制数的补码的数字左移右移填充,其余没有数字填充的空缺补0,而另一种>>>与>>也不同,用符号位填补高位,会使数字发生巨大变化,没有<<<符,位运算优先级比加减乘除低- 计算机补码机制(浅谈):在计算机中数字以二进制字节存在,一个字节(byte)由8个位(bit)组成,每个数字在计算机中都以补码形式存在,正数补码就是原码本身,负数的补码是对应正数原码每位取反
~后+1,例:-5的补码为1111 1111 1111 1111 1111 1111 1111 1011,也可见计算机组成原理
System.out.println(5<<2);//运行结果是20 System.out.println(5>>2);//运行结果是1 System.out.println(5>>3);//结果是0 System.out.println(-5>>3);//结果是-1 System.out.println(-5>>>3);//结果是536870911- 计算机补码机制(浅谈):在计算机中数字以二进制字节存在,一个字节(byte)由8个位(bit)组成,每个数字在计算机中都以补码形式存在,正数补码就是原码本身,负数的补码是对应正数原码每位取反

1.4 基本结构(循环、判断)
判断
if(condition1) statement1 else if(condition2) statement2 else statement3switch(i){ case 1:...;break;case 2:...;break;default:...;break;}判断与C++等其他语言差不多循环
- 标准
do{ ...}while()和while(){...}与C++相同 for(int i = 0;i < n;i++)基本循环与C++相同foreach循环是java中的泛型循环,java5增加的内容,类似python的for i in iterable或C++11的for(Type VarName : Array)- 循环的中断:使用break;和continue;可以实现循环退出和开始下一次循环,如果是多重循环,要对其它外层循环执行退出或开始下一次的话,许多语言要通过goto语句实现,java有goto关键字但是没有goto语句,但可通过标签指定中断的循环
- 标准
//这里有一个示例说明了 break 语句的工作状态。请注意,标签必须放在希望跳出的最外
//层循环之前, 并且必须紧跟一个冒号。
Scanner in = new Scanner(System.in);
int n;
read_data:
while (. . .) // this loop statement is tagged with the label
for (. . .) // this inner loop is not labeled
{
Systen.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 readjata loop
}
// this statement is executed immediately after the labeled break
if (n < 0) // check for bad situation
{
// deal with bad situation
}
else
{
// carry out normal processing
}
//如果输入有误,通过执行带标签的 break 跳转到带标签的语句块末尾。对于任何使用
//break语句的代码都需要检测循环是正常结束, 还是由 break 跳出。1.5 输入输出
在java中,打印输出到“标准输出流”(即控制台窗口)是一件非常容易的事情,只要调用
System.out.println即可。然而,读取“ 标准输人流”System.in就没有那么简单了。要想通过控制台进行输入,首先需要构造一个 Scanner 对象,并与“标准输入流”System.in关联。Scanner in = new Scanner(System.in);现在,就可以使用 Scanner 类的各种方法实现输入操作了。例如, nextLine 方法将输入一行System.out.print("What is your name? ");String name = in.nextLine();在这里,使用 nextLine 方法是因为在输入行中有可能包含空格。要想读取一个单词(以空白符作为分隔符,) 就调用String firstName = in.next();要想读取一个整数, 就调用 nextlnt 方法。System.out.print("How old are you? ");int age = in.nextlnt();与此类似,要想读取下一个浮点数, 就调用 nextDouble 方法。
Scanner使用的输入方法 注意:Scanner 类定义在java.util 包中。 当使用的类不是定义在基本java.lang 包中时,一定要使用import 指示字将相应的包加载进来。在程序的最开始添加上一行:
import java.util.*;使用控制台命令输入:因为输入是可见的, 所以 Scanner 类不适用于从控制台读取密码。Java SE 6 特别引入了 Console 类实现这个目的。要想读取一个密码, 可以采用下列代码:
Console cons = System.console();String username = cons.readLine("User name: ");cha [] passwd = cons.readPassword("Password:");- 为了安全起见, 返回的密码存放在一维字符数组中, 而不是字符串中。在对密码进行处理之后,应该马上用一个填充值覆盖数组元素 采用 Console 对象处理输入不如采用 Scanner 方便。每次只能读取一行输入, 而没有能够读取一个单词或一个数值的方法。
- 在java.Iang.System中,有static Console console()实现创建Console类,如果有可能进行交互操作, 就通过控制台窗口为交互的用户返回一个 Console 对象,否则返回 null。对于任何一个通过控制台窗口启动的程序, 都可使用 Console 对象, 否则, 其可用性将与所使用的系统有关
- 在java.io.Console中有
static char[] readPassword(String prompt, Object...args)static String readLine(String prompt, Object...args)显示字符串 prompt 并且读取用户输入,直到输入行结束。args 参数可以用来提供输入格式。
格式化输出:Java SE 5.0 沿用了 C语言库函数中的 printf方法。例如,调用 System.out.printf("%8.2f",10000.0 / 3.0); 可以用 8 个字符的宽度和小数点后两个字符的精度打印数字。也就是说,打印输出一个空格和7 个字符, 如下所示:
3333.33- 在 printf中,可以使用多个参数, 例如:
System.out.printf("Hello, %s. Next year, you'll be SSd", name, age);每一个以 % 字符开始的格式说明符都用相应的参数替换



- 在 printf中,可以使用多个参数, 例如:
文件输入输出:
- 要想对文件进行读取,就需要一个用 File 对象构造一个 Scanner 对象,如下所示:
Scanner in = new Scanner(Paths.get("niyflle.txt"), "UTF-8");如果文件名中包含反斜杠符号,就要记住在每个反斜杠之前再加一个额外的反斜杠:“ c:\\mydirectory\\myfile.txt ”,在这里指定了 UTF-8 字符编码,如果省略字符编码, 则会使用运行这个 Java 程序的机器的“ 默认编码”。这不是一个好主意,如果在不同的机器上运行这个程序,可能会有不同的表现。 创建完毕,就可以利用前面介绍的任何一个 Scanner 方法对文件进行读取。 - 要想写入文件, 就需要构造一个 PrintWriter 对象。在构造器中,只需要提供文件名:
PrintWriter out = new Printlulriter('myfile.txt", "UTF-8");如果文件不存在,创建该文件。 可以像输出到 System.out—样使用 print、 println 以及 printf命令。
- 要想对文件进行读取,就需要一个用 File 对象构造一个 Scanner 对象,如下所示:
1.6 大数
- 如果基本的整数和浮点数精度不能够满足需求, 那么可以使用java.math 包中的两个 很有用的类:Biglnteger 和 BigDecimaL 这两个类可以处理包含任意长度数字序列的数值
- Biglnteger 类实现了任意精度的整数运算, BigDecimal 实现了任意精度的浮点数运算。
- 使用静态的 valueOf方法可以将普通的数值转换为大数值:
Biglnteger a = Biglnteger.valueOf(100);遗憾的是,不能使用人们熟悉的算术运算符(如:+ 和 *) 处理大数值。 而需要使用大数值类中的 add 和 multiply 方法。Biglnteger c = a.add(b); // c = a + bBiglnteger d = c.multiply(b.add(Biglnteger.valueOf(2))); // d = c* (b + 2)
与 C++ 不同, Java 没有提供运算符重载功能。 程序员无法重定义+和*运算符
1.7 数组
类似其他语言的数组,在C++中这种定义方式类似于数组指针,
int[] a = new int[100];,通过a.length可访问数组的大小,允许定义长度为0的数组(不是null)- 创建一个数字数组时, 所有元素都初始化为 0。boolean 数组的元素会初始化为 false 对象数组的元素则初始化为一个特殊值 null, 这表示这些元素(还)未存放任何对象。
- 一旦创建了数组,就不能再改变它的大小(尽管可以改变每一个数组元素。如果经常需要在运行过程中扩展数组的大小,就应该使用另一种数据结构—数组列表(array list)
数组的初始化: 在 Java中, 提供了一种创建数组对象并同时赋予初始值的简化书写形式。下面是一例子:
int[] small Primes = { 2, 3, 5, 7, 11, 13 };请注意, 在使用这种语句时,不需要调用 new。但是还可以初始化一个匿名的数组:new int[] { 17, 19, 23, 29, 31, 37 }这种表示法将创建一个新数组并利用括号中提供的值进行初始化,数组的大小就是初始值的 个数。 使用这种语法形式可以在不创建新变量的情况下重新初始化一个数组。例如:small Primes = new int[] { 17, 19, 23, 29, 31, 37 };这是下列语句的简写形式:
int[] anonymous = { 17, 19, 23, 29, 31, 37 };
smallPrimes = anonymous;- 数组的拷贝 在 Java 中,允许将一个数组变量拷贝给另一个数组变量。这时, 两个变量将引用同一个数组:
int[] luckyNumbers = smallPrimes;1uckyNumbers[5] = 12; // now smallPrimes[5] is also 12- 如果希望将一个数组的所有值拷贝到一个新的数组中去,就要使用 Arrays 类的 copyOf方法:
int[] copiedLuckyNumbers = Arrays.copyOf(luckyNumbers , luckyNumbers .length);第 2 个参数是新数组的长度。这个方法通常用来增加数组的大小:luckyNumbers = Arrays.copyOf(luckyNumbers , 2 * luckyNumbers.length); - 如果数组元素是数值型,那么多余的元素将被赋值为 0 ; 如果数组元素是布尔型,则将赋值为 false。相反,如果长度小于原始数组的长度,则只拷贝最前面的数据元素。
- 如果希望将一个数组的所有值拷贝到一个新的数组中去,就要使用 Arrays 类的 copyOf方法:
- 数组的方法:在Arrays类中有大量的方法,包括快速排序,二分查找等
- 多维数组与一维数组类似,同C++数组初始化或使用new初始化变量就可
- main方法的String args[]参数(命令行参数):在命令行使用java class文件 -g cruel world时,后面的参数-g、cruel、world就作为命令行参数传递给args[0],args[1],args[2]
- 不规则数组:
int[][] adds = new int[NMAX + 1][];java中没有定义上的多维数组,每一行数组长度可以在使用的时候单独指定,odds[n] = new int[n + 1];
java.util.Arrays储存了数组有用的函数,详情可以看官方文档 给数组赋值:通过 fill 方法。 对数组排序:通过 sort 方法,按升序。 比较数组:通过 equals 方法比较数组中元素值是否相等。 查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。
