1. Java语言简介
1. JVM
JVM是Java虚拟机的简称,是运行所有Java程序的平台,是Java程序的运行环境我们编写的Java代码,都运行在 JVM 之上。这是Java跨平台的原理
Java跨平台的原理图
2. JRE和JDK
- JRE (Java Runtime Environment) :是Java程序的运行时环境,包含 JVM 和运行时所需要的 核心类库 。
- JDK (Java Development Kit):是Java程序开发工具包,包含 JRE 和开发人员使用的工具。
2. Java数据类型
Java的数据类型分为两大类:
- 基本数据类型: 整数 、 浮点数 、 字符 、 布尔
- 引用数据类型: 类 、 数组 、 接口
1. 基本数据类型
2. 引用数据类型
类 (Class)、 数组(Array) 、 接口(interface) 可以看成一个地址值
3. 数据类型转换
- 自动转换:将 取值范围小的类型自动提升为取值范围大的类型
(byte、short、char‐‐>int‐‐>long‐‐>float‐‐>double)
public static void main(String[] args) {
int i = 1;
byte b = 2;
( byte x = b + i; 报错)
//int类型和byte类型运算,结果是int类型
int j = b + i;
System.out.println(j);
}
- 强制转换:将取值范围大的类型强制转换成取值范围小的类型
转换格式:数据类型 变量名 = (数据类型)被转数据值;
例如
int i = (int)1.5;
浮点转成整数,直接取消小数点,可能造成数据损失精度。
int强制转成short砍掉2个字节,可能造成数据丢失。
3. 运算符
1. 算数运算符
自增。自减,运算符号
int a = 1;
int b = a++; 先b=a=1, 然后a在自加
若 int b = ++a; 先a自加 a=2 然后 b=a=2;
2. 赋值运算符
赋值运算符,就是将符号右边的值,赋给左边的变量
3. 比较运算符
比较运算符,是两个数据之间进行比较的运算,运算结果都是布尔值 true 或者 false
4. 逻辑运算符
逻辑运算符,是用来连接两个布尔类型结果的运算符,运算结果都是布尔值 true 或者 false
5. 三元运算符
格式:数据类型 变量名 = 布尔类型表达式?结果1:结果2 真一,假二
布尔类型表达式结果是true,三元运算符整体结果为结果1,赋值给变量。
布尔类型表达式结果是false,三元运算符整体结果为结果2,赋值给变量。
例如
public static void main(String[] args) {
int i = (1==2 ? 100 : 200);
System.out.println(i); //200
int j = (3<=4 ? 500 : 600);
System.out.println(j); //500
}
4. Java方法
1. 定义格式
修饰符 返回值类型 方法名 (参数列表)
{
代码...
return ;
}
例如
public void method(){
.....................
.....................
return null;
}
2. 构造方法
构造方法:用来创建对象的方法,特点,没有返回值修饰符,方法名=类名
1 默认构造方法(没有返回值,没有参数,方法名=类名)
public class Car {
Car默认构造方法
public Car() {
}
}
2 有参构造方法(没有返回值,有参数,方法名=类名),可以在创建对象时,直接获得需要的参数
public class Car {
public Double price;
有参数构造方法
public Car(Double price) {
this.price = price;
}
}
3. 静态方法
静态方法:static关键字修饰的方法,不需要创建对象,就可以调用该方法,注意:静态方法只能调用静态变量
public class Car {
定义一个静态方法
public static void staticMethod(){
System.out.println("这是一个静态方法,可以直接调用");
}
}
public class dome01 {
public static void main(String[] args) {
不用创建对象,直接调用该方法
Car.staticMethod();
}
}
4 方法重载
方法重载:指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返回值类型无关
public class Car {
public void method(){
System.out.println("方法method");
}
public void method(int a){
System.out.println("方法method");
}
public void method(byte a){
System.out.println("方法method");
}
}
注意在写方法是传递参数:方法的参数为基本类型时,传递的是数据值. 方法的参数为引用类型时,传递的是地址值.
5. Java变量
- 类变量:独立于方法之外的变量,用 static 修饰。
- 成员变量:独立于方法之外的变量,不过没有 static 修饰。
- 局部变量:类的方法中的变量。
例如
public class Variable{
static int allClicks=0; 类变量
String str="hello world"; 成员变量(实例变量)
public void method(){
int i =0; 局部变量
}
}
成员变量与局部变量的区别
- 成员变量有默认值 ,局部变量没有默认值
- 成员变量在堆内存,局部变量在栈内存
- 成员变量作用在类中,局部变量在方法中,即括号外面的不能被调用
访问权限修饰符
-
default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
-
private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
-
public : 对所有类可见。使用对象:类、接口、变量、方法
-
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
6. 流程控制语句
1. 判断语句
if 语句
满足条件就执行括号里面的语句,否则不执行
if(条件){ 这里的条件一定为一个布尔值(true或者false)
语句体;
}
例如
if(3<4){
System.out.println("3<4");
}
System.out.println("。。。。。。。。。。。。");
if…else 语句
满足条件就执行括号里面的语句1,否则执行语句2
if(条件) {
语句体1;
}
else {
语句体2;
}
例如
if(3<4){
System.out.println("3<4");
}else {
System.out.println("3>=4");
}
if…else if…else 语句
满足那个条件执行那一个括号里的语句,否则执行最后一个else括号里的语句
```java
if (条件1) {
执行语句1;
} else if (条件2) {
执行语句2;
}...
}else if (条件n) {
执行语句n;
} else {
执行语句n+1;
}
例如
从键盘中输入一个数字
int getNumber = new Scanner(System.in).nextInt();
if (getNumber == 0) {
System.out.println("这个数等于0");
} else if (getNumber>0) {
System.out.println("这个数大于0");
}else if(getNumber<0){
System.out.println("这个数大于0");
} else {
System.out.println("错误");
}
2. 选择语句
switch 语句
通过条件值与常量值相比对(条件不在去限定一定是布尔值),符合便执行语句并跳出选择,若是没有一个符合便,执行默认的(default) 语句
switch(条件) { 这里的条件不需要在去限定一定是布尔值了,什么都可以
case 常量值1: 语句体1; break;
case 常量值2: 语句体2; break;
...
default: 语句体n+1; break;
}
例如
//定义变量,判断是星期几
int weekday = 6;
//switch语句实现选择
switch (weekday) { int类型的常量作为判断条件
case 1: System.out.println("星期一");break;
case 2: System.out.println("星期二");break;
case 3: System.out.println("星期三");break;
case 4: System.out.println("星期四");break;
case 5: System.out.println("星期五");break;
case 6: System.out.println("星期六");break;
case 7: System.out.println("星期日");break;
default: System.out.println("你输入的数字有误");break;
注意:在switch语句中,如果case的后面不写break,将出现穿透现象,也就是不会在判断下一个case的值,直接向后运行,直到遇到break,或者整体switch结束。
3. 循环语句
for 语句
判断是否满足条件需要一次,若满足条件执行循环体,条件改变,再次判断是否满足条件。直到条件不能满足为止
for(初始条件; 进行判断(布尔值); 循环一次的变化){
循环体
}
例如
for(int x = 0; x < 10; x++) {
System.out.println("HelloWorld"+x);
}
while 语句
原理和上面的for都差不多
while(进行判断(布尔值)){
循环体
循环一次的变化
}
例如:计算1到100的和
计算1到100的和
int i=0;int number = 0;
while (i<=100){
number=number+i;
i++;
}
System.out.println(number);
do…while 语句
do…while会先干一次,在判断
do{
循环体
循环一次的变化
}while(进行判断(布尔值));
例如
int x = 1;
do {
System.out.println("HelloWorld");
x++;
} while (x <= 0);
即使不满足条件,也会先运行一次
4. break与continue
break
break:终止switch或者循环
for (int i = 1; i <= 10; i++) {
需求:打印完两次HelloWorld之后结束循环
if (i == 3) {
break; 只会运行2次
}
System.out.println("HelloWorld" + i);
}
continue
continue:跳过本次循环,继续下一次的循环
for (int i = 1; i <= 10; i++) {
需求:不打印第三次HelloWorld
if (i == 3) {
continue; 当i=3时,下面的语句将不在执行
}
System.out.println("HelloWorld" + i);
}
练习9x9乘法表
for (int i = 1; i < 10; i++) {
for (int j = 1; j < i+1; j++) {
System.out.print(i+"*"+j+"="+j*i+" ");
}
System.out.println();
}
结果如下图
7. 数组
1. 数组基础
数组特征:长度固定,内容一致
定义方式
数组存储的数据类型[] 数组名字 = new 数组存储的数据类型[长度];
int[] arr = new int[3]
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3...};
int[] arr = new int[]{1,2,3,4,5};
数据类型[] 数组名 = {元素1,元素2,元素3...};
int[] arr = {1,2,3,4,5};
数组的访问:数组索引:arr[3] 从0开始, 数组长度: 数组名.length
2. 数组常用方法
在Java中,有提供数组工具的一个类Arrays,这个类中有常用的数组工具方法,而这些方法都是静态方法,可以直接调用。介绍几个,其余的自行查看API
public static String toString(Array); 通过给定任意类型的数组,返回该数组的字符串表现形式,为一个String对象
public static <T> List<T> asList(Array); 通过给定非基本数据类型的数组,获得一个list集合
public static boolean equals(Array1,Array2); 比较2个数组内容是否相等
public static void sort(int[] a) :对指定的 int 型数组按数字升序进行排序
toString方法
通过给定任意类型的数组,返回该数组的字符串表现形式,为一个String对象
String[] arr = {"a","b","c","d","e"};
toString方法:将任意数组,转为字符串
String s = Arrays.toString(arr);
System.out.println(s);
asList方法
通过给定非基本数据类型的数组,获得一个list集合
- 该集合不支持add和remove方法
- 该集合与数组链接起来,当更新其中之一时,另一个自动更新
- 该集合存储的数据不能是基本数据类型
String[] arr = {"a","b","c","d","e"};
/asList方法,将数组转换为一个集合,注意:该方法不适用于基本数据类型(byte,short,int,long,float,double,boolean)
/①该集合不支持add和remove方法 ②该集合与数组绑定在一起,当更新其中之一时,另一个自动更新
List<String> lists = Arrays.asList(arr);
System.out.println(lists.toString()); // [a, b, c, d, e]
/②该集合与数组链接起来,当更新其中之一时,另一个自动更新
arr[4]="j";
System.out.println(lists.toString()); // [a, b, c, d, j]
/②该集合与数组链接起来,当更新其中之一时,另一个自动更新
lists.set(2,"w");
System.out.println(lists.toString()); // [a, b, w, d, j]
显示结果如下
从上面结果可以发现改变其一,另一个也改变
equals方法
比较2个数组内容是否相等
int[] arr1 = {1,2,4};
int[] arr2 = {1,2,4};
boolean b = Arrays.equals(arr1, arr2);
System.out.println(b); //true
sort方法
对指定的 int 型数组按数字升序进行排序,这个方法有许多重载,例如可以对double排序等
int[] arr1 = {10,2,4,3};
Arrays.sort(arr1);
System.out.println(Arrays.toString(arr1)); //[2, 3, 4, 10]
8. 继承
1. 继承简介
继承就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为
使用extends关键字
class 父类 {
...
}
class 子类 extends 父类 {
...
}
子类就可以调用父类的方法,和变量等(非私有)
public class Cat extends animal { // 继承父类
public static void main(String[] args) {
/ 创建一个子类对象
Cat cat = new Cat();
/ 调用父类参数
System.out.println(cat.age); // 0
cat.eat(); //吃饭
cat.sleep(); //睡觉
}
}
class animal{
/ 父类的成员变量
int age;
/父类的方法
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
2. 方法的重写
如果成员方法不重名,这时的调用是没有影响的,但是一但重名,我们称其为重写
方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现,重写可增强了父类的功能,实现自己的需求
子类
public class Cat extends animal { // 继承父类
public static void main(String[] args) {
/ 创建一个子类对象
Cat cat = new Cat();
cat.eat(); //吃饭
}
/ 我们对eat方法复写加强其功能
public void eat(){
System.out.println("加强功能1");
super.eat();
System.out.println("加强功能2");
}
}
父类
class animal{
public void eat() {
System.out.println("吃饭");
}
}
显示结果
关于构造方法
- 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
- 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个 super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。
class Fu {
private int n;
Fu() {
System.out.println("父类的构造方法");
}
}
class Zi extends Fu {
子类的构造方法会默认调用父类的构造方法
Zi() {
System.out.println("子类的构造方法");
}
}
public class dome04 {
public static void main(String[] args) {
Zi zi = new Zi();
}
}
3. 抽象类
抽象方法
使用 abstract 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体实现步骤,留给子类去具体实现,抽象方法只定义顶层规则(方法名,返回值,参数列表)
说人话,抽象方法就是制定顶层规则的方法,至于怎么实现规则,那是你子类的事情
修饰符 abstract 返回值类型 方法名 (参数列表);
public abstract void run();
抽象类
如果一个类含有了抽象方法,那么该类必须是抽象类
抽象方法
public abstract class dome05 {
抽象方法
public abstract void method01();
public abstract void method02();
public abstract void method03();
非抽象方法
public void method04();
其他的成员变量
int a;
...........
}
例如
public abstract class dome05 {
抽象方法
public abstract void method01();
public static void main(String[] args) {
System.out.println("ggggg");
}
public void method02(){
System.out.println("xxxxx");
}
}
重点:抽象方法必被子类去实现
其他
- 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象,因为假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
- 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的,因为子类的构造方法中,有默认的super(),需要访问父类构造方法
- 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
- 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类
9. 接口
1. 接口概述
接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法(JDK9)
接口可以理解为特殊的抽象类
接口的使用,它不能创建对象,但是可以被实现( implements ,类似于被继承)。一个实现接口的类(可以看做是接口的子类),需要实现接口中所有的抽象方法。
2. 定义格式
public interface 接口名称 {
抽象方法
默认方法
静态方法
私有方法
}
例如
public interface dome06 {
抽象方法
public void method01();
默认方法(default关键字修饰): 供子类直接调用或者子类重写
public default void method2() {
}
静态方法(static关键字修饰): 供接口直接调用
public static void method3() {
}
私有方法(private关键字修饰): 供接口中的默认方法或者静态方法调用
private void method4() {
}
}
例如
public interface dome06 {
// 抽象方法
public void method01();
public default void method02() {
System.out.println("method02");
//默认方法,可以调用该接口一切方法
method01();
method02();
method03();
method04();
}
public static void method03() {
System.out.println("method03");
// 只能调用静态修饰的方法
method03();
}
private void method04() {
System.out.println("method04");
//私有方法,可以调用该接口一切方法
method01();
method02();
method03();
method04();
}
}
3. 接口的实现
抽象方法的使用
1 单个接口的实现
1 定义一个接口
public interface dome01 {
public void getMoney();
}
2 实现接口
public class dome02 implements dome01 {
@Override
public void getMoney() {
System.out.println("得到money");
}
}
2 多个接口的实现
接口1
public interface dome01 {
public void getMoney();
}
接口2
public interface dome03 {
public void getLife();
}
子类实现
public class dome02 implements dome01,dome03 {
@Override
public void getMoney() {
System.out.println("得到money");
}
@Override
public void getLife() {
System.out.println("得到生命");
}
}
默认方法的使用
默认方法可以继承,可以重写,二选一,但是只能通过实现类的对象来调用
1 重写默认方法
接口
public interface dome01 {
默认方法
public default void defaultMethod(){
System.out.println("接口默认方法");
}
}
实现类
public class dome02 implements dome01 {
重写了默认方法
public void defaultMethod(){
System.out.println("子类重写了接口默认方法");
}
}
***************************************************
2 直接调用默认方法
接口
public interface dome01 {
默认方法
public default void defaultMethod(){
System.out.println("接口默认方法");
}
}
实现类
public class dome02 implements dome01 {
public void method(){
直接调用接口的方法
defaultMethod();
}
}
静态方法的使用
静态方法:只能使用接口名调用,不可以通过实现类的类名或者实现类的对象调用
所以,有没有implements去实现并不重要,重要有接口名称.xxxx方法就可调用该静态方法
接口
public interface dome01 {
public static void staticMethod(){
System.out.println("接口的静态方法");
}
}
调用者
public class dome02 {
public static void main(String[] args) {
dome01.staticMethod();
}
}
私有方法的使用
私有方法:只有默认方法可以调用。
私有静态方法:默认方法和静态方法可以调用。
如果一个接口中有多个默认方法,并且方法中有重复的内容,那么可以抽取出来,封装到私有方法中,供默认方法去调用。从设计的角度讲,私有的方法是对默认方法和静态方法的辅助者的一个角色。
4. 其他
- 接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰
- 接口中,没有构造方法,不能创建对象。
- 接口中,没有静态代码块。
10. 多态
1. 多态的体现
什么是多态?同一行为,通过不同的事物,可以体现出来的不同的形态。在Java中,同一个父类的方法,在不同的子类可以表现出不同的实现方式,即称为多态
父类类型 变量名 = new 子类对象;
变量名.方法名();
*********************************************************
例如
Fu f = new Zi();
f.method();
*********************************************************
创建集合对象也是使用多态
List<String> list = new ArrayList<>();
注意:当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写后方法
2. 引用类型转换
向上转型:
向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的,当父类引用指向一个子类对象时,便是向上转型。例如上面的2个例子都是向上转型
向下转型
向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
子类类型 变量名 = (子类类型) 父类变量名;
例如:
List<String> list = new ArrayList<>();
向下转型
ArrayList ls=(ArrayList) list;
注意事项:在向下转型的时候,必须保证转型的目标对象与被转型对象创建时的子类一致
在上面的例子中,转型的目标对象是ArrayList,创建时子类对象也为 ArrayList,才能转型成功
11. this,super与static关键字
1. this关键字
this关键字指的就是当前自己
ppublic class dome01 {
int a;
public void method1() {
System.out.println("11111");
}
public void method2() {
this.method1();
this.a=100;
}
}
在方法2中,通过this关键字,指到自己找到方法1,所以this关键字就是指向自己本身
在继承中,this关键字,会首先在自身里面去找,找不到了,再去父类中去找
2. super关键字
如果说this关键字指向的是自己的话,那么super指向的是自己的父类
父类
public class dome02 {
public void method(){
System.out.println("父类的方法");
}
}
子类
public class dome03 extends dome02 {
public void method(){
System.out.println("子类的方法");
}
public void runMethod(){
调用自己的方法
this.method();
调用父类的方法
super.method();
}
public static void main(String[] args) {
new dome03().runMethod();
}
}
结果显示
3. static关键字
static关键字的使用,它可以用来修饰的成员变量和成员方法,被修饰的成员是属于类的,而不是单单是属于某个对象的。也就是说,既然属于类,就可以不靠创建对象来调用了
静态方法
修饰符 static 返回值类型 方法名 (参数列表){
执行语句
}
1 静态方法可以直接访问类变量和静态方法。
2 静态方法不能直接访问普通成员变量或成员方法。反之,成员方法可以直接访问类变量或静态方法。
3 静态方法中,不能使用this关键字
4. 静态代码块
静态代码块:定义在成员位置,使用static修饰的代码块{ }。 位置在类中方法外,再执行时,随着类的加载而执行且执行一次,优先于main方法和构造方法的执行,一般用来配置某些基本设置
public class dome03 {
static {
System.out.println("静态代码块");
}
public static void main(String[] args) {
}
}