Java核心技术总结一:Java的基本程序设计结构
- 一、注释
- 二、数据类型
- 三、变量与常量
- 四、运算符
- 五、字符串
- 六、输入与输出
- 七、控制流程
- 八、大数
- 九、数组
一、注释
// 单行注释
/* */ 多行注释
/** */ 自动生成文档
二、数据类型
类型 存储需求 取值范围
byte 1字节 -128 ~ 127
short 2字节 -32768 ~ 32767
int 4字节 -2147483648 ~ 2147483647
long 8字节 -9223372036854775808 ~ 9223372036854775807
补充:
长整型整数有后缀L或l,十六进制有前缀0x或0X,八进制有前缀0
jdk1.7以后,加上前缀0b或者0B就可以写成二进制数,如0B1001即为9
jdk1.7以后,可以为数字加上下划线,使其更易读,如1_000_000即为100万
Java没有任何无符号形式的byte、short、int、long类型
类型 存储需求 取值范围
float 4字节 大约±3.402 823 47E+38F(有效位数为6~7位)
double 8字节 大约为±1.797 693 134 862 315 70E+308(有效位数为15位)
补充:
float类型有后缀F或f,没有后缀F的浮点数值(如3.14)默认为double类型
浮点数不适用于无法接受舍入误差的金融计算,如2.0-1.1=0.8999999...
不是期望的0.9,如果在计算中不允许有误差,就应该使用BigDecimal类
Java中的char类型占2字节,16位,其采用Unicode字符(ASCll码也包含在类)
常用的ASCll码:
0-9:48-57
A-Z:65-90
a-z: 97-122
有两个值:true和false,用来判断逻辑条件。
补充:
整型值和布尔值不能进行相互转换
如if(x=0),在C++中可以编译运行,其结果总为false,而java中不能通过编译,因为整数表达式x=0不能转换为布尔值
三、变量与常量
变量比较简单,这里说下注意点:
1.变量声明后必须使用赋值语句对变量进行显式初始化,不能使用未初始化的变量
如 int a;System.out.println(a);//错误,a未初始化
2.变量的声明尽可能靠近变量第一次使用的地方
3.jdk10以后,如果可以从变量的初始值推断出它的类型,
就不需要声明类型,只需要使用关键字var而无需知道类型
如 var number=12;//number为int类型;
var name=“zhangsan”;//name为String类型
1.java中,利用关键字final指示常量,final表示该变量一旦被赋值无法更改
2.习惯上,常量名使用全大写
3.如果希望某个常量可以在一个类的多个方法中使用,可以将其设置为类常量,
使用关键字static final进行设置(类常量定义于main方法的外部)
针对某个变量的取值只在一个有限的集合里,可以自定义枚举类型
如
enum Size{SMALL,MEDIUM,LARGE};
Size s=Size.LARGE;
四、运算符
+、-、*、/,%
/运算需要注意,当参与/操作的两个操作数都是整数时,表示整数除法;否则,表示浮点除法,如15/2=7,15.0/2=7.5
注意:整数被0除将产生1个异常;浮点数被0除将得到无穷大或NaN结果
1.Math.sqrt(x),计算x的平方根
2.Math.pow(x,a),计算x的a次方,返回值为double类型
3.最接近π的常量:Math.PI;最接近e的常量:Math.E
说明:
1.只要在源文件顶部加上import static java.lang.Math.*;则使用Math类置的函数与常量不需要加Math
例如:
import static java.lang.Math.*;
public class test {
public static void main(String[] args) {
System.out.println(sqrt(PI));
}
}
2.java中数学运算如果计算溢出,数学运算符只是返回一个错误结果而不做任何提示,
如:1000000000*3=-1294967295,因为int最大值才刚超过20亿,
此时可以采用Math.multiplyExact(1000000000,3)进行计算,它就会产生一个异常
1.合法转换:
byte->short->int->long(double);char->int->long(double);float->double
int-->float;long-->float;long-->double
->转换表示无信息丢失,-->表示可能有精度的丢失
如int n=123456789;float f=n;//f =1.2345679E8 ;这是因为123456789包含的位数比float类型所能够表示的位数多.
2.当用一个二元运算符连接两个值时(例如n+f),先要将两个操作数转换为同一操作数,再进行计算。
规则如下:
两个操作数有一个为double类型,则另外一个转为double型
否则有一个为float类型,则另外一个转为float型
否则有一个为long类型,则另外一个转为long型
否则,两个操作数都将被转为int型
上一节可以看到,在必要时int会自动转成double,但当需要将double转成int时,需要使用强制类型转换。
语法格式为:在圆括号中给想要转换的目标类型,后面紧跟待转换的变量名。
例如:double x=9.96;int y=(int)x;/y=9;
注意:
如果试图将一个数值从一种类型强制转换为另一种类型,而又超出了目标类型的表示范围,结果就会截断成一个完全不同的值,例如,(byte)300的实际值为44
1.结合赋值和运算符 (+=,-=;*=;/=,%=...)
如x+=4;等价于x=x+4;
注意:如果x为一个int型,则x+=3.5,即x=(int)(x+3.5),发生强制类型转换
2.自增减运算符(n++,++n,n--,--n)
在表达式中,前缀会先进行±1操作,而后缀会先使用变量原来的值
如 int m=4;int n=3*m++;//n=12;m=5
int m=4;int n=3*++m;//n=15;m=5
3.关系和boolean运算符
- 检测相等性,使用==,如3==7的值为false
检测不相等,使用!=,如3!=7的值为true
还有常用的<,>,<=,>=
2.expression1&& expression2:
逻辑与:当两个表达式都为true结果为true,否则为false
expression1|| expression2
逻辑或:当两个表达式只要有一个为true结果为true,否则为false
注意:逻辑与和或都按照短路方法求值,即如果expression1可以确定结果,expression2不进行计算。
3.condition?expression:expression2
当condition为true,结果就为expression1,否则为expression2
1.&(and),|(or),^(xor),~(not)
如3&7=7,(011&111=3)
注意&,|也可用在布尔值上,此时其与&&,||相似,只不过不采用短路方法计算。
2.左移<<,右移>>
如1<<3结果为8
注意右移时如果不够移,则结果为0,如1>>2结果为0;
注意:移位操作符的右操作数要完成模32的运算(如果左操作数为long型,则为模64),
例如1<<35等价于1<<3
优先级 运算符 结合性
1 ()、[]、{} 从左向右
2 !、+、-、~、++、-- 从右向左
3 *、/、% 从左向右
4 +、- 从左向右
5 «、»、>>> 从左向右
6 <、<=、>、>=、instanceof 从左向右
7 ==、!= 从左向右
8 & 从左向右
9 ^ 从左向右
10 | 从左向右
11 && 从左向右
12 || 从左向右
13 ?: 从右向左
14 =、+=、-=、*=、/=、&=、|=、^= 从右向左
、~=、«=、»=、>>>=
五、字符串
String的substring方法可以从一个较大的字符串提取出一个子串。例如:
Stirng father="hello";
String son=father.substring(0,3); //son即为"he"
substring第二个参数是不想复制的第一个位置,本例从0到2复制
substring的工作方式有一个优点;容易计算子串的长度。s.substring(a,b)的长度为b-a
1.java允许使用+连接(拼接)两个字符串
当将一个字符串与一个非字符串的值进行拼接时,后者会转换成字符串。
如 int num=2020;String year=“this year is”+num;//year为字符串"this year is 2020".
2.jdk11中,提供了repeat方法
Stirng repeated="Java".repeat(3);//repeated为字符串"JavaJavaJava"
由于不能修改java字符串中的单个字符,所以在java文档中将String类对象称为是
不可变的,如 String a="hello",“hello”这个值不可以修改,但是可以修改字
符串变量a,使得其引用另外一个字符串,如 a=“hi”。
不可变字符串有一个优点:编译器可以让字符串共享:可以想象将各种字符串存放在公
共的存储池中。字符串变量指向存储池中相应的位置。如果复制一个字符串变量,原
始字符串与复制的字符串共享相同的字符。
1.可以使用equals方法检测连个字符串是否相等
s.equals(t):如果字符串s和字符串t相等,返回true,否则返回false。
一定不要用==运算符检测两个字符串是否相等(该运算符只能确定两个字符串是否存
放在同一个位置,但完全有可能将内容相同的多个字符串副本放置在不同的位置)
1.空串""是长度为0的字符串(可以使用sr.length()==0或者str.equals(“”))
检查字符串是否为空
2.String可以存放一个特殊的值->nul,要检查一个字符串是否为null,要使用
str==null进行判断。
有时需要检查一个字符串既不是null也不是空串,可以使用以下条件进行判断:
str!=null&&ste.length()!=0
注意:两者顺序不能颠倒,如果在一个null值上调用方法,会出现错误
所有上文的equals方法,如果字符串a不为null,则应该使用a.equals(b)来判断
a和b是否相等,因为b可能存在为null的情况。
每次拼接字符串时,都会构建一个新的Sring对象,既耗时有浪费空间,使用
StringBuilder类可以避免这个问题的发生。
例如;
StringBuilder sb=new StringBuilder();
sb.append("hello");
sb.append("world");
String s= sb.toString();
//通过这种方式创建了字符串s,其值为"helloworld”。
扩展: StringBuilder在jdk1.5引入,其前身是 StringBuffer,效率
比 StringBuilder低,但是它允许采用多线程方式添加或删除字符。而
StringBuilder不能,如果所有字符串编辑操作都在单线程中执行,则
应该使用 StringBuilder。
六、输入与输出
想要通过控制台进行输入,需要构造一个与“标准输入流”System.in关联的
Scanner对象。下面例子展示如何从控制台输入并获取值。
Scanner sc=new Scanner(System.in);
System.out.println("please input your name");
String name=sc.nextLine();//获取控制台输入
Scanner不只有nextLine方法,还有nextInt,next等多种方法,详见jdkAPI
jdk1.5沿用了C语言函数库的printf方法
例如
double x=1.12345678;
System.out.printf("%8.2f",x);
//输出为 1.12
//这包括8个字符,其中精度为小数点后2个字符,所以会打印前导空格和4个字符。
读取文件:
Scanner in = new Scanner(Path.of("myfile.txt"), StandardCharsets.UTF_8);
写入文件:
PrintWriter out = new PrintWriter("myfile.txt", StandardCharsets.UTF_8);
注意:如果一个不存在的文件构造一个Scanner或者一个无法创建的文件名构造一个PrintWriter,就会产生一个异常。
七、控制流程
块(即复合语句)是指有若干条java语句组成的语句,并用一对大括号括起来。块定义
了变量的作用域。一个块可以嵌套在另一个块中。
如:
public static void main(String[] args) {
int n;
//...
{
int k;
//...
}
}
但不能在嵌套的两个块中声明相同的变量。
如:
//无法通过编译
public static void main(String[] args) {
int n;
//...
{
int n;
int k;
//...
}
}
int a=1;
int b=2;
if(a>b){
System.out.println("a");
}
if(a>b){
System.out.println("a");
}else{
System.out.println("b");
}
if(a>b){
System.out.println("a");
}else if(a==b){
System.out.println("==");
}else{
System.out.println("b");
}
int num=1;
int sum=0;
while(num<=5){
sum+=num;
num++;
}
System.out.println(sum);
do {
sum+=num;
num++;
} while(num<=5);
System.out.println(sum);
int sum=0;
for (int j = 0; j <=5 ; j++) {
sum+=j;
}
System.out.println(sum);
int choice= (int)(Math.random()*4);
switch (choice){
case 0:
System.out.println("0");
break;
case 1:
System.out.println("1");
break;
case 2:
System.out.println("2");
break;
default:
System.out.println("3");
}
int sum=0;
for (int i = 0; i <=5 ; i++) {
if(i==1){
continue;
}
sum+=i;
}
System.out.println(sum);
sum=0;
for (int i = 0; i <=5 ; i++) {
if(i==1){
break;
}
sum+=i;
}
System.out.println(sum);
八、大数
如果基本的整数和浮点数精度不能够满足需求,
可以使用java.math包中两个很有用的类,BigInteger和BigDecimal,
BigInteger类实现任意精度的整数计算
BigDecimal类实现任意精度的浮点数计算
1.使用静态的valueof方法可以将普通数值转换为大数
BigInteger a=BigInteger.valueOf(100);
2.对于更大的数,可以使用一个带字符串参数的构造器:
BigInteger bigInteger = new BigInteger("4632879378293728937298378983793728937812937812");
3.不能使用熟悉的算术运算符处理大数(如+和*),而是使用大数的add和multipy方法
BigInteger c=a.add(b);//c=a+b
BigInteger d=c.multiply(b);//d=c*b
九、数组
int []a;
a=new int[100];
int []b={
2,3,4,5};
int []c=new int[0];
int len=a.length;
for (int i = 0; i <a.length ; i++) {
a[i]=i;
}
for (int element: a){
System.out.println(element);
}
int []aa=a;
aa[5]=12;
int []copyA= Arrays.copyOf(a,a.length);
copyA[6]=16;
int []sort={
4,1,3,2};
Arrays.sort(sort);
int [][]m;
m=new int[10][10];
for (int i = 0; i <m.length ; i++) {
for (int j = 0; j <m[i].length ; j++) {
m[i][j]=i*10+j;
}
}
for (int i = 0; i <m.length ; i++) {
for (int j = 0; j <m[i].length ; j++) {
System.out.println(m[i][j]);
}
}
for (int []row:m){
for (int value:row){
System.out.println(value);
}
}