hello everyone,here is java world!
/**
* 可以用来自动创建文档的注释
*/
public class Hello {
public static void main(String[] args) {
// 向屏幕输出文本
System.out.println("Hello, world!");
/*
* 可以用来自动创建文档的注释
*/
}
} // class定义结束
java程序最基本的结构:
class 类名 {
}
java对格式没有明确要求,多几个空格或者换行都没有关系,但是会我们要养成良好的编程习惯,遵守java社区约定的编程格式
class
Hello
{
}
我们前面提到的Eclipse的快捷键:Ctrl+Shift+F可以帮助我们快速格式化代码,Eclipse就是按照约定的格式对代码进行格式化的,如果要知道java代码的具体格式要求,可以在Eclipse的设置中找到
因为java是面向对象语言,所以程序的基本单元就是class,class的命名规则需要注意:
类名必须是英文字母、数字、下划线的组合
类名必须以英文首字母开头
要注意遵守命名习惯,好的命名:Hello、NoteBook、VRPlayer
不好的命名:hello(首字母没大写)、Good123(123无实际意义)、Note_Book(带下划线)、_World(下划线开头)
public用来修饰当前类是公开的,不写public也可以正常编译,但是这样无法从命令行执行,在一个class的内部我们可以定义很多方法,方法的定义是由返回值、方法名称、参数构成,方法内部定义的是一组执行语句,方法内部的代码将会被JVM执行
public class 类名 {
返回值 方法名 (参数) {
}
}
java程序规定的入口程序必须是
`public static void main(String[] args) {
}
方法名也有好的命名和不好的命名,和class一样,但是首字母要小写:
好的命名:main、goodMorning、playVR
不好的命名:Main(首字母大写)、good123(123无实际意义)、good_morning(带下划线)、_playVR(下划线开头)
在方法的括号中间,语句是真正的执行代码,每一句必须以分号结尾
System.out.println(“Hello, world!”);
什么是注释:注释是给人阅读的、编译器会自动忽略注释,java的注释总共有三种:
单行注释:以 // 开头,到当前行尾
多行注释:用 /* … / 表示,以 / 开头,/ 结尾,中间的所有内容都被视为注释
特殊的多行注释:用 /** … / 表示,以 /* 开头,/ 结尾,写在类和方法的定义处,可用于自动创建文档
类似于数学的方程式:y = x2 + 1,其中y和x都是变量
变量的一个重要特点:可以重新被赋值,我们可以看下面的执行过程
我们可以在Eclipse里用debug模式运行,一步步观察打印结果,当我们点击debug运行,Eclipse会提示我们切换到debug模式,我们点击Yes,并勾选Remember my decision(记住我的决定),这样下次就不会再提示了
整数类型:long、int、short、byte
浮点类型:double、float
布尔类型:boolean
字符类型:char
计算机内存最小的存储单元是位(bit),基本计量单位是字节,一个字节是8位,二进制数:00000000 ~ 11111111(0 ~ 255),内存单元从0开始编号,称为内存地址,一个存储单元相当于一个字节
java类型对应计算机中的字节个数:
byte:8位,1个字节,范围-128~127(-27 ~ 27 - 1)
short:16位,2个字节,范围-32768~32767(-215 ~ 215 - 1)
int:32位,4个字节,范围(-231 ~ 231 - 1)
long:64位,8个字节,范围(-263 ~ 263 - 1),long形整数定义时需要在数字末尾加上 L (小写 l 不推荐使用,容易和数字1混淆),例如:long x = 10L;不加 L 编译默认定义为int类型
float:32位,4个字节,需要在结尾加上 f ,一个浮点类型可以用科学计数法来表示:float f = 3.14e38f(3.14 * 10 38)
double:64位,8个字节
boolean:1位,1/8个字节,只有两个值,true和false,通常用来比较计算结果,例如:boolean x = 5 >3;
char:16位,2个字节,只能表示一个字符,用单引号表示,例如:char x = ‘中’;
同一个数的不同进制表现是完全不同的:15 = 0xf(16进制) = 0b1111(二进制),为什么将小数称为浮点数,是因为它的小数点是可以浮动的,例如这两个数是相等的:12.34e5 = 1.234e6,我们要区分字符和字符串类型,字符类型用单引号表示,并且只能有一个字符
public class IntType {
public static void main(String[] args) {
byte b = 127; // -128 ~ +127
short s = 32767; // -32768 ~ +32767
int i = 2147483647; // -2147483648 ~ +2147483647
long l = 9_000_000_000_000_000_000L; // -9223372036854775808 ~
// +9223372036854775807
System.out.println(b);
System.out.println(s);
System.out.println(i);
System.out.println(l);
int i3 = 2_000_000_000;
int i4 = 0xff0000; // 十六进制表示的十进制16711680
int i5 = 0b1000000000; // 二进制表示的十进制512
System.out.println(i3);
System.out.println(i4);
System.out.println(i5);
// 输出十六进制表示的整型:
System.out.println(Integer.toHexString(12345678)); // bc614e
// 输出二进制表示的整型:
System.out.println(Integer.toBinaryString(12345678)); // 101111000110000101001110
}
}
常量就是用final修饰的变量
常量初始化后不可再次赋值
常量名通常全部大写
常量用来避免意外赋值
常量用来代替Magic Number(魔幻数字,硬编码值,一段时间之后容易忘记代表的含义)
public class Constant {
public static void main(String[] args) {
final double PI = 3.14;
// PI = 3.1415; // 编译报错
double r = 4.0;
double length = PI * r * 2;
double area = PI * r * r;
System.out.println(length);
System.out.println(area);
// magic number:
double salary = 12500.0;
double pay = salary * (1 - 0.2);
// final double TAX_RATE = 0.2;
// double pay = salary * (1 - TAX_RATE);
System.out.println(pay);
}
}
基于四则运算规则
除法结果为整数
除数为0,运行时会报错,但编译不会报错
java提供了++运算和–运算符,++n或者n++代表n = n + 1,–n或者n–代表n = n - 1,运算符在数字前代表先+1再引用,运算符在数字后代表先引用再+1
java提供了+=和-=运算符,n += 100相当于n = n + 100,n -= 100相当于n = n - 100
public class Div {
public static void main(String[] args) {
int i = 99 / 9;
System.out.println(i);
// 整数运算的结果仍然是整数:
int n = 100 / 9;
System.out.println(n);
int z = 100 / 0; // 报错,错误信息会告诉我们错误类型以及具体在哪一行,后面的语句不会执行
System.out.println(z);
}
}
整数运算需要注意
计算结果溢出不报错,但是计算结果不正确,例如:int x = 2147483647 + 1;计算结果为-2147483648
解决方案:用范围更大的整形进行运算,long x = 2147483647L + 1
左移:<<
带符号右移:>>
不带符号右移:>>>
byte和short会先转换为int再进行移位
int n1 = 5;
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
---|
int n2 = n1 << 10; // 5120
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
---|
int n3 = n2 >> 11; // 2,最右边的1超出了范围,所以被丢弃
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
---|
int n4 = n1 << 29; // -1610612736,最高位表示的是符号位,所以表示的是一个负数
1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
---|
int n5 = n4 >> 29; // -3,符号位会被保留
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
---|
int n5 = n4 >>> 29; // 5,符号位不会被保留
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
---|
与运算:&,位上的值都是1才是1,否则为0,1 & 1 = 1; 1 & 0 = 0; 0 & 1 = 0; 0 & 0 = 0;
或运算:|,位上的值有一个1就是1,否则为0,1 | 1 = 1; 1 | 0 = 1; 0 | 1 = 1; 0 | 0 = 0;
异或运算:^,位上的值不相同则为1,相同为0,1 ^ 0 = 1; 0 ^ 1 = 1; 1 ^ 1 = 0; 0 ^ 0 = 0;
非运算:, 1 = 0,~ 0 = 1;
int n1 = 0x03_83_d0_25;
0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 |
---|
int n2 = 0x00_00_ff_ff;
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
---|
int n3 = n1 & n2; // 53285, 0x00_00_d0_25
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 |
---|
int n4 = n1 | n2; // 0x03_83_ff_ff
0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
---|
由高到低:
1.~ ++ --
2.* / %
3.+ -
4.<< >>
5.&
6.|
一般我们很难记住这些运算符的优先级,所以可以使用括号()来明确执行顺序
在运算过程中,计算结果为较大类型的整形
short s = 12; int i = 100 + s; long n = 999 * i;
可以将结果强制转型,(类型)变量或数值
int y1 = (int) (n - 199); int y2 = (int) n - 199;
强制转型可能会丢失精度,当超过最大位数,会将高位全部抛弃
int z = (int) (n * 100000000)
我们要选择合适的类型进行运算,没有必要为了节省内存使用byte或short,因为它们表示的范围太小
很多浮点数无法精确表示,例如:double a = 0.1;二进制表示:0.0 0011 0011 0011…,这是一个无限小数,计算机不可能在有限的内存中表示一个无限的小数
计算有误差:double b = 1 - 9/10; 理论上结果应该是0.1,但是因为浮点数无法精确表示,所以在计算过程中会有误差
整形可以自动提升到浮点形:double d1 = 1.2 + 24.0/5; 结果是6.0
特别注意,类型不能自动提升的情况:double d1 = 1.2 + 24/5; 结果是5.2
public class FloatOps {
public static void main(String[] args) {
double a = 0.1;
double b = 1 - 9.0 / 10;
System.out.println(a); // 0.1
System.out.println(b); // 0.09999999999999998
// 注意没有自动提升的情况:
double d1 = 1.2 + 24.0 / 5; // 6.0
double d2 = 1.2 + 24 / 5; // 5.2
System.out.println(d1);
System.out.println(d2);
}
}
浮点数计算有几个特殊值需要注意:
NaN:Not a Number
Infinity:无穷大
-Infinity:负无穷大
public class NaN {
public static void main(String[] args) {
double d1 = 0.0 / 0; // NaN
double d2 = 1.0 / 0; // Infinity
double d3 = -1.0 / 0; // -Infinity
System.out.println(d1);
System.out.println(d2);
System.out.println(d3);
}
}
强制转为整形会直接扔掉小数位
四舍五入的技巧
超出整形范围会自动变为最大值
public class ToInt {
public static void main(String[] args) {
int n1 = (int) 12.3; // 12
int n2 = (int) 12.7; // 12
int n3 = (int) (12.7 + 0.5); // 13
int n4 = (int) 1.2e20; // 2147483647
System.out.println(n1);
System.out.println(n2);
System.out.println(n3);
System.out.println(n4);
}
}
关系运算:< ,<=,>,>=,==,!=
与运算:&&
或运算:||
非运算:!
与运算:&&,参与运算的操作数只要有一个是false那么就是false,所以确定为false后,后面的运算操作将不再进行运算,例如:boolean and = false && (5 / 0 > 0); // false
或运算:||,参与运算的操作数只要有一个是false那么就是true,所以确定为true后,后面的运算操作将不再进行运算,例如:boolean or = true || (5 / 0 > 0); // true
因为短路运算符的规则,(5 / 0 > 0)将不会运行,否则程序将会报错
根据条件b计算x或y:b ? x : y
x和y只计算其中一个
x和y类型必须相同
字符类型是基本数据类型,一个char类型保存一个字符,他可以保存一个英文字符,也可以保存一个中文字符
java使用Unicode编码来表示字符,我们要看一个char类型的Unicode编码,可以直接将一个char类型赋值给int类型,这个int类型的值就是Unicode编码,例如:
int x = 'A'; // 65
int y = '中'; // 20013
我们也可以直接用Unicode编码来表示,方法是用\u + 4位16进制数表示:
char x = '\u0041'; // 'A'
char y = '\u4e2d'; // '中'
字符串类型不是一个基本类型,它是引用类型
字符串类型String,表示一个字符串,字符串内容用双引号表示,字符串内容并不包含开头结尾的两个双引号
转移字符:
如果我们需要表示一些特殊字符,我们就需要用到转移字符,常用的转移字符:\n,",\r,\t,\
字符串最常用的操作是字符串连接,用+连接,我们可以连接两个字符串也可以将字符串和其他类型进行连接,例如:
String x = "hello" + ",world!"; String y = "age is " + 12;
字符串是引用类型,字符串是不可变的
引用类型特点:变量指向某个对象,而不是持有某个对象
所有的应用类型都可以指向一个特殊的值:null(空值),当我们给一个引用变量赋值为null,我们可以认为当前变量不指向任何对象,但是空值null和空字符串是不一样的,空字符串也是一个对象,例如:
String s = null;
System.out.println(s); // null
String t = "";
System.out.println(t);
区分字符类型(基本类型)和字符串类型(引用类型)
基本类型的变量是持有某个数值
引用类型的变量是指向某个对象
引用类型的变量可以是null
区分空(null)和空字符串("")
当有一组类型相同的变量时,可以用数组表示
数组类型是"类型[]",数组初始化用 new 类型[长度],例如:int[] ns = new int[5]; 也可以直接指定初始化元素,由编译器自动为我们推算出数组的大小,例如:int[] ns = new int[] {68, 79, 91, 85, 61}; 还可以进一步简写,例如:int[] ns = {68, 79, 91, 85, 61};
数组初始化所有元素为默认值,对于int数组默认值全部都是0
数组创建后大小不可变,即数组长度不可变,但数组变量是可以指向另一个数组对象
数组索引从0开始
可以用 数组变量.length 获取数组长度
数组是一种引用类型的变量
使用索引(下标)访问数组元素,索引超出范围将报错
public class Hello {
public static void main(String[] args) {
// 5位同学的成绩
int n1 = 68;
int n2 = 79;
int n3 = 91;
int n4 = 85;
int n5 = 61;
int[] ns = new int[5];
ns[0] = 68;
ns[1] = 79;
ns[2] = 91;
ns[3] = 85;
ns[4] = 61;
System.out.println(ns.length); // 5
System.out.println(ns[2]); // 91
System.out.println(ns[5]); // Error!
ns = new int[] {1, 2, 3}; // 这是可行的,数组本身没有变,只是ns变量从一个数组对象指向另一个数组对象,数组本身是没有变的,它只是创建了一个新的数组对象
String[] names = {"xiaoming", "xiaohong", "xiaojun"}; // 字符串数组的每一个元素都指向一个字符串对象
names[2] = "daniu"; // 将原来数组2号位的指向从xiaojun指向了新的字符串daniu
}
}
public class Main {
public static void main(String[] args) {
int[] ns1 = new int[5]; // { 0, 0, 0, 0, 0 }
int[] ns2 = new int[] { 1, 3, 5, 7, 9 };
int[] ns3 = { 2, 4, 6, 8, 10 };
int[] ns4 = ns3;
System.out.println("ns1.length: " + ns1.length);
System.out.println("ns2.length: " + ns2.length);
System.out.println("ns3.length: " + ns3.length);
// 现在ns3和ns4指向同一个数组:
System.out.println("ns3[1]: " + ns3[1]);
ns3[1] = 999;
System.out.println("ns4[1]: " + ns4[1]);
// 把ns3指向一个新数组:
ns3 = new int[] { 1, 2, 3 };
ns3[1] = 888;
System.out.println("ns4[1]: " + ns4[1]);
// String数组:
String[] strs = { "Abc", "Xyz", "123" };
strs[1] = "Hello";
}
}
打印结果:
ns1.length: 5
ns2.length: 5
ns3.length: 5
ns3[1]: 4
ns4[1]: 999
ns4[1]: 999
数组是同一数据类型的集合
数组是引用类型
数组元素是值类型(如int[])或引用类型(如String[])
数组一旦创建大小不可变
可以通过索引访问数组元素
索引超出范围将报错