第一个HelloWorld程序
使用工具:IDEA或Eclipse或Sublime或文本编辑器 编写第一个HelloWorld程序
(Sublime和文本编辑器)这两个需要用命令运行 javac编译 java运行
// 声明/定义一个公开(public)的类(class),起个名字叫HelloWorld
public class HelloWorld{
// 类体
/* 整个这一块的代码被称为:主(main)方法(程序的入口,SUN公司java语言规定的)
JVM在执行程序的时候,会主动去找这样一个方法。没有这个规格的方法,程序是无法执行的。
注意:方法必须放到“类体”中,不能放到“类体”外面。
任何一个程序都要有一个入口,没有入口进不来,无法执行。
*/
//声明/定义一个公开(public) 静态(static)(修饰符) void(方法无返回值) 方法名为main (String[] args)←参数 参数类型为String数组 参数名为args
//主(main)方法入口。
public static void main(String[] args){
// 方法体
/*
注意:方法体由一行一行的“java语句”构成
并且非常重要的是:任何一条java语句必须以“;”结尾,并且这个分号还得是英文的,不能用中文分号。
";" 代表一条语句的结束。
非常重要的是:方法体中的代码遵循自上而下的顺序依次逐行执行。
*/
System.out.println("HelloWorld");
// System.out.println();这行代码的作用是向控制台打印字符串。
// 注意:如果println后面小括号里的内容是一个“字符串”的话,必须使用英文双引号括起来。
// println是换行输出,print是不换行输出
// 只要是括号或引号都必须是成对的
}
}
局部变量和成员变量的区别
- 定义的位置不一样
局部变量:在方法的内部
成员变量:在方法的外部,直接写在类当中 - 作用范围不一样
局部变量:只有方法当中才可以使用,出了方法就不能再用了
成员变量:整个类都可以通用 - 默认值不一样
局部变量:没有默认值,如果要想使用,必须手动进行赋值
成员变量:如果没有赋值,会有默认值,规则和数组一样 - 内存的位置不一样
局部变量:位于栈内存
成员变量:位于堆内存 - 生命周期不一样
局部变量:随着方法进栈而诞生,随着方法出栈而消失
成员变量:随着对象的创建而诞生,随着对象被垃而消失
变量初始化
变量:可被再次赋值改变的量
错误的初始化方式:
int a;
System.out.println(a); //编译报错因为变量a没被初始化
正确的初始化方式:
int a;
a=1
System.out.println(a);
int a=1;
System.out.println(a);
常量
常量:用final修饰的变量是不可被再次赋值的
用于修饰类、属性和方法
- 被final修饰的类不可以被继承
- 被final修饰的方法不可以被重写
- 被final修饰的变量不可以被改变,被final修饰不可变的是变量的引用,而不是引用指向的内容,引用指向的内容是可以改变的
final int a =1;
//a=2;这里编译报错 因为用final修饰的变量是不可被再次赋值的
System.out.println(a);
数据类型
定义:Java语言是强类型语言,对于每一种数据都定义了明确的具体的数据类 型,在内存中分配了不同大小的内存空间。
分类:
基本数据类型
- 整数类型(byte,short,int,long)
- 浮点类型(float,double)
- 字符型(char)
- 布尔型(boolean)
引用数据类型
- 类(class)
- 接口(interface)
- 数组([])
注意:两个byte类型相加,会自动转成int进行相加,否则需要强制转换byte
(所以不用担心结果超出127会不会造成精度缺失,它是先提升为int在进行运算,只有你强转为byte时才可能会精度缺失)
byte类型的取值范围?
byte是 [-128 ~ 127] 共可以标识256个不同的数字。
byte类型的最大值是怎么计算出来的?
byte是1个字节,是8个比特位,所以byte可以存储的最大值是:
01111111
注意:在计算机当中,一个二进制位最左边的是符号位,当为0时表示正数,
当为1时表示负数。所以byte类型最大值是:01111111
那么是不是2的7次方-1呢?
是不是:10000000(前边是一个二进制) - 1
byte类型最大值是:2的7次方 - 1.
有几个取值范围需要大家记住:
(1个字节)byte: [-128 ~ 127]
(2个字节)short:[-32768 ~ 32767] 可以表示65536个不同的数字
(4个字节)int: [-2147483648 ~ 2147483647]
(2个字节)char: [0~65535] 可以表示65536个不同的数字
short和char实际上容量相同,不过char可以表示更大的数字。
因为char表示的是文字,文件没有正负之分,所以char可以表示
更大的数字。
对于8种基本数据类型来说:
其中byte,short,int,long,float,double,boolean,这7种类型计算机表示起来
比较容易,因为他们都是数字。其中布尔类型只有两个值true和false,实际上
true和false分别在C++中对应的是1和0,1为true,false为0。
对于char类型来说计算机表示起来比较麻烦,因为char对应的是文字,每一个国家
的文字不一样,文字不能直接通过“自然算法”转换成二进制。这个时候怎么办?
字符编码诞生了。
什么是字符编码?
字符编码是人为的定义的一套转换表。
在字符编码中规定了一系列的文字对应的二进制。
字符编码其实本质上就是一本字典,该字段中描述了文字与二进制之间的对照关系。
字符编码是人为规定的。(是某个计算机协会规定的。)
字符编码涉及到编码和解码两个过程,编码和解码的时候必须采用同一套字符编码
方式,不然就会出现乱码。
关于字符编码的发展过程?
起初的时候计算机是不支持文字的,只支持科学计算。实际上计算机起初是为了
战争而开发的,计算导弹的轨道....
后来随着计算机的发展,计算机开始支持文字,最先支持的文字是英文,英文
对应的字符编码方式是:ASCII码。
ASCII码采用1byte进行存储,因为英文字母是26个。(键盘上所有的键全部算上也
超不过256个。1byte可以表示256种不同的情况。所以英文本身在计算机方面就占有
优势。)
'a' --(采用ASCII码进行编码)-> 01100001
01100001 --(采用ASCII码进行解码)-> 'a'
如果编码和解码采用的不是同一个编码方式,会出现乱码。
'b' ---> 98
'c' ---> 99...
'a' ---> 97
'A' ---> 65
'B' ---> 66
...
'0' ---> 48 (这个'0'不是那个0,是文字'0')
'1' ---> 49
随着计算机语言的发展,后来国际标准组织制定了ISO-8859-1编码方式,
又称为latin-1编码方式,向上兼容ASCII码。但不支持中文。
后来发展到亚洲,才支持中文,日文,韩文....
中文这块的编码方式:GB2312<GBK<GB18030 (容量的关系)
以上编码方式是简体中文。
繁体中文:big5(台湾使用的是大五码。)
在java中,java语言为了支持全球所有的文字,采用了一种字符编码方式
叫做unicode编码。unicode编码统一了全球所有的文字,支持所有文字。
具体的实现包括:UTF-8 UTF-16 UTF-32....
需要记住:
ASCII('a'是97 'A'是65 '0'是48...)
ISO-8859-1(latin-1)
GB2312
GBK
GB18030
Big5
unicode(utf8 utf16 utf32)
Java数据类型转换(自动转换和强制转换)
数据类型的转换,分为自动转换和强制转换。自动转换是程序在执行过程中“悄然”进行的转换,不需要用户提前声明,一般是从位数低的类型向位数高的类型转换;强制类型转换则必须在代码中声明,转换顺序不受限制。
自动数据类型转换
自动转换按从低到高的顺序转换。不同类型数据间的优先关系如下:
低--------------------------------------------->高
byte,short,char-> int -> long -> float -> double
强制数据类型转换
高--------------------------------------------->低
强制转换的格式是在需要转型的数据前加上“( )”,然后在括号内加入需要转化的数据类型。有的数据经过转型运算后,精度会丢失,而有的会更加精确。
下面的例子可以说明这个问题
public class Demo {
public static void main(String[] args){
int x;
double y;
x = (int)34.56 + (int)11.2; // 丢失精度
y = (double)x + (double)10 + 1; // 提高精度
System.out.println("x=" + x);//x=45
System.out.println("y=" + y);//y=56.0
}
}
由于在 34.56 前有一个 int 的强制类型转化,所以 34.56 就变成了 34。同样 11.2 就变成了 11 了,所以 x 的结果就是 45。在 x 前有一个 double 类型的强制转换,所以 x 的值变为 45.0,而 10 的前面也被强制成 double 类型,所以也变成 10.0,所以最后 y 的值变为 56。
Java语言采用何种编码方案?有何特点?
Java语言采用Unicode编码标准,Unicode(标准码),它为每个字符制订了一 个唯一的数值,因此在任何的语言,平台,程序都可以放心的使用。
注释
什么Java注释?
**定义:用于解释说明程序的文字
分类
单行注释 格式: // 注释文字
多行注释 格式: / 注释文字 /
文档注释(一般用在方法或类上) 格式:/ 注释文字 */
作用
在程序中,尤其是复杂的程序中,适当地加入注释可以增加程序的可读性,有利 于程序的修改、调试和交流。注释的内容在程序编译的时候会被忽视,不会产生 目标代码,注释的部分不会对程序的执行结果产生任何影响。 注意事项:多行和文档注释都不能嵌套使用。
访问修饰符 public,private,protected,以及不写(默认)时的 区别
**定义:**Java中,可以使用访问修饰符来保护对类、变量、方法和构造方法的访 问。Java 支持 4 种不同的访问权限。
分类
- private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部 类)
- default (即缺省,什么也不写,不使用任何关键字): 在同一包内可见,不使用 任何修饰符。使用对象:类、接口、变量、方法。
- protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意: 不能修饰类(外部类)。
- public : 对所有类可见。使用对象:类、接口、变量、方法
Java中equals和==的区别
- ==是判断两个变量或实例是不是指向同一个内存空间,equals是判断两个变量或实例所指向的内存空间的值是不是相同
- ==是指对内存地址进行比较 , equals()是对字符串的内容进行比较
- ==指引用是否相同, equals()指的是值是否相同
Java中默认的 equals方法实现如下:
public boolean equals(Object obj) {
return (this == obj);
}
而String类则覆写了这个方法,直观的讲就是比较字符是不是都相同。
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
构造方法及其作用
构造方法作用就是对类进行初始化。 如果你没有定义任何构造方法的形式会为你取一个不带任何参数的构造函数,那么你产生类的对像时只能用不带参数的方法,如:class a {}//没有任何构造函数。
构造方法就是与类同名的那个方法,它的作用是可以用来初始化,例子如下
class Person {//人类
public Person(String n,int a){ //构造方法
name = n; age = a;
}
private string name;
private int age;
}
static void main(String[] args){
Person p = new Person("张三",14);//这就是作用
}
new一个对象的时候要用到构造函数,
new一个对象的时候要用到构造函数,
例如Hello hello = new Hello();这时调用的是Hello的无参数构造方法;
Hello hello = new Hello(“hi”);这个是调用Hello有参数构造方法,
在JAVA中如果不写构造方法的话,会默认加上一个无参数的构造方法,但是如果已经有了一个有参数的构造方法,那么无参数的构造方法就不会默认被加上.
如果Hello类中已经有了一个有参数的构造方法,这时再使用 Hello hello = new Hello();来创建对象的时候就会出错,这就是为什么书上要强调写了有参数的构造方法就最好加一个无参数的构造方法.
运算符
算术运算符 + - * / % ++ –
一元运算符
int a = 12;
System.out.println(-a);
int b = a++;
System.out.println(b);
b = ++a;
System.out.println(b);
二元运算符
int a = 4, b = 2, c = 3;
int d = a * (b + c) % c;
public static void main(String[] args) {
float f1 = 9 % 4;// 保存取余后浮点类型的结果
double da = 9 + 4.5; // 双精度加法
double db = 9 - 3.0; // 双精度减法
double dc = 9 * 2.5; // 双精度乘法
double dd = 9 / 3.0; // 双精度除法
double de = 9 % 4; // 双精度取余
System.out.println("整数的算术运算"); // 整数的加、减、乘、除和取余
System.out.printf("9+4=%d \n", 9 + 4);
System.out.printf("9-4=%d \n", 9 - 4);
System.out.printf("9*4=%d \n", 9 * 4);
System.out.printf("9/4=%d \n", 9 / 4);
System.out.printf("9%%4=%d \n", 9 % 4);
System.out.println("\n浮点数的算术运算"); // 浮点数的加、减、乘、除和取余
System.out.printf("9+4.5f=%f \n", 9 + 4.5f);
System.out.printf("9-3.0f=%f \n", 9 - 3.0f);
System.out.printf("9*2.5f=%f \n", 9 * 2.5f);
System.out.printf("9/3.0f=%f \n", 9 / 3.0f);
System.out.printf("9%%4=%f \n", f1);
System.out.println("\n双精度数的算术运算"); // 双精度数的加、减、乘、除和取余
System.out.printf("9+4.5=%4.16f \n", da);
System.out.printf("9-3.0=%4.16f \n", db);
System.out.printf("9*2.5=%4.16f \n", dc);
System.out.printf("9/3.0=%4.16f \n", dd);
System.out.printf("9%%4=%4.16f \n", de);
System.out.println("\n字符的算术运算"); // 对字符的加法和减法
System.out.printf("'A'+32=%d \n", 'A' + 32); //'A'+32=97
System.out.printf("'A'+32=%c \n", 'A' + 32); //'A'+32=a
System.out.printf("'a'-'B'=%d \n", 'a' - 'B'); //'a'-'B'=31
}
算术赋值运算符 += -= *= /= %=
1. int a = 1;
2. int b = 2;
3. a += b; // 相当于 a = a + b
4. System.out.println(a);
5. a += b + 3; // 相当于 a = a + b + 3
6. System.out.println(a);
7. a -= b; // 相当于 a = a - b
8. System.out.println(a);
9. a *= b; // 相当于 a=a*b
10. System.out.println(a);
11. a /= b; // 相当于 a=a/b
12. System.out.println(a);
13. a %= b; // 相当于 a=a%b
14. System.out.println(a);
关系运算符 == != > >= < <=
a > b // 比较变量a的值是否大于变量b的值
x+y> = z // 比较变量x与变量y的和是否大于或等于变量z的值
width * width+size != area // 比较变量width的平方加上变量size的值是否与变量area的值不相等
name == "zhht" // 比较变量name的值是否等于字符串nzht
pass != "123456" // 比较变量pass的值是否不等于字符串“123456”
逻辑运算符 & | ^ ! && ||
运算符 | 用法 | 含义 | 说明 | 实例 | 结果 |
---|---|---|---|---|---|
&& | a&&b | 短路与 | ab 全为 true 时,计算结果为 true,否则为 false。 | 2>1&&3<4 | true |
|| | a||b | 短路或 | ab 全为 false 时,计算结果为 false,否则为 true。 | 2<1||3>4 | false |
! | !a | 逻辑非 | a 为 true 时,值为 false,a 为 false 时,值为 true | !(2>4) | true |
| | a|b | 逻辑或 | ab 全为 false 时,计算结果为 false,否则为 true | 1>2|3>5 | false |
& | a&b | 逻辑与 | ab 全为 true 时,计算结果为 true,否则为 false | 1<2&3<5 | true |
- && 与 & 区别:如果 a 为 false,则不计算 b(因为不论 b 为何值,结果都为 false)
- || 与 | 区别:如果 a 为 true,则不计算 b(因为不论 b 为何值,结果都为 true)
- 注意:短路与(&&)和短路或(||)能够采用最优化的计算方式,从而提高效率。在实际编程时,应该优先考虑使用短路与和短路或。
位运算符 & | ^ ~ << >> >>>
运算符 | 含义 | 实例 | 结果 |
---|---|---|---|
& | 按位进行与运算(AND) | 4 & 5 | 4 |
| | 按位进行或运算(OR) | 4 | 5 | 5 |
^ | 按位进行异或运算(XOR) | 4 ^ 5 | 1 |
~ | 按位进行取反运算(NOT) | ~ 4 | -5 |
运算符 | 含义 | 实例 | 结果 |
---|---|---|---|
» | 右移位运算符 | 8»1 | 4 |
« | 左移位运算符 | 9«2 | 36 |
复合位运算符 | 含义 | 实例 | 结果 |
---|---|---|---|
&= | 按位与赋值 | num1 &= num2 | 等价于 num 1=num 1 & num2 |
|= | 按位或赋值 | num1 |= num2 | 等价于 num 1=num 1 | num2 |
^= | 按位异或赋值 | num1 ^= num2 | 等价于 num 1=num 1 ^ num2 |
-= | 按位取反赋值 | num1 ~= num2 | 等价于 num 1=num 1 ~ num2 |
«= | 按位左移赋值 | num1 «= num2 | 等价于 num 1=num 1 « num2 |
»= | 按位右移赋值 | num1 »= num2 | 等价于 num 1=num 1 » num2 |
int a = 1;
int b = 2;
int c = 3;
a &= 4;
a |= 4;
a ^= c;
a -= 6;
b >>= 1;
c <<= 1;
System.out.println("a = " + a);//a=1
System.out.println("b = " + b);//b=1
System.out.println("c = " + c);//c=6
&和&&的区别
&运算符有两种用法:
- 按位与
- 逻辑与
&&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要 求运算符左右两端的布尔值都是true 整个表达式的值才是 true。&&之所以称
为短路运算,是因为如果&&左边的表达式的值是 false,右边的表达式会被直 接短路掉,不会进行运算。
**注意:**逻辑或运算符(|)和短路或运算符(||)的差别也是如此。
关键字
Java关键字是编程语言中事先定义好的,有特别意义的标识符,在编程中不能被编程者用来定义变量名、类名、方法名等。
Java 有没有 goto?
goto 是 Java 中的保留字,在目前版本的 Java 中没有使用。
final finally finalize区别
- final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值。
- finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
- finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调用,当我们调用System.gc()
方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的最后判断。
this关键字的用法
this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。
this的用法在java中大体可以分为3种:
- 普通的直接引用,this相当于是指向当前对象本身。
- 形参与成员名字重名,用this来区分:
public Person(String name , int age){
this.name=name;
}
- 引用本类的构造函数
class Person{
private String name;
private int age;
public Person(){
}
public Person(String name){
this.name=name;
}
}
super关键字的用法
super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。
super也有三种用法:
- 普通的直接引用
与this类似,super相当于是指向当前对象的父类的引用,这样就可以用super.xxx来引用父类的成员。 - 子类中的成员变量或方法与父类中的成员变量或方法同名时,用super进行区分
- 引用父类构造函数
super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。 this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。
public class Person {
protected String fatherName;
public Person(String FatherName) {
this.fatherName = FatherName;
}
}
public class Student extends Person {
private String studentName;
public Student(String name1, String name2) {
super(name1);
this.studentName = name2;
}
public void getInfo() {
System.out.println(this.studentName); //Child
System.out.println(super.fatherName); //Father
}
}
}
public class Test {
public static void main(String[] args) {
Student s1 = new Student("Father", "Child");
s1.getInfo();
}
}
this与super的区别
-
super
它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参) -
this
它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名) -
super()和this()类似,区别是
super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。 -
super()和this()均需放在构造方法内第一行。
-
尽管可以用this调用一个构造器,但却不能调用两个。
-
this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
-
this()和super()都指的是对象,所以,均不可以在static环境中使用。
包括:static变量,static方法,static语句块。 -
从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。
static存在的主要意义
- static的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法!
- static关键字还有一个比较关键的作用就是:用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。
static的独特之处
- 被static修饰的变量或者方法是独立于该类的任何对象,也就是说,这些变量和方法不属于任何一个实例对象,而是被类的实例对象所共享。
- 在该类被第一次加载的时候,就会去加载被static修饰的部分,而且只在类第一次使用时加载并进行初始化,注意这是第一次用就要初始化,后面根据需要是可以再次赋值的。
- static变量值在类加载的时候分配空间,以后创建类对象的时候不会重新分配。赋值的话,是可以任意赋值的!
- 被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。
static应用场景
因为static是被类的实例对象所共享,因此如果某个成员变量是被所有对象所共享的,那么这个成员变量就应该定义为静态变量。
因此比较常见的static应用场景有
- 修饰成员变量
- 修饰成员方法
- 静态代码块
- 修饰类【只能修饰内部类也就是静态内部类】
- 静态导包
static注意事项
- 静态只能访问静态
- 非静态既可以访问非静态的,也可以访问静态的
包
包在操作系统中其实就是一个文件夹。包是用来分门别类的管理技术,不同的技术类放在不同的包下,方便管理和维护。
包名的命名规范
路径名.路径名.xxx.xxx
- 包名一般是公司域名的倒写。例如:黑马是www.baidu.com,包名就可以定义成com.baidu.技术名称。
- 包名必须用”.“连接。
- 包名的每个路径名必须是一个合法的标识符,而且不能是Java的关键字。
什么时候需要导包?
情况一:在使用Java中提供的非核心包中的类时
情况二:使用自己写的其他包中的类时(分布式开发时必用到)
什么时候不需要导包?
情况一:在使用Java核心包(java.lang)中的类时
情况二:在使用自己写的同一个包中的类时