Java

# Java ## 常量 ### 常量概述 常量:是指在Java程序中固定不变的数据。 ### 常量分类 | 常量类型 | 含义 | 数据举例 | | ---------- | -------------------------------------- | ---------------------- | | 整数常量 | 所有的整数 | 0,1,520,982674 | | 小数常量 | 所有的小数 | 0.1,-0.3,3.141592653 | | 字符常量 | 单引号包含,只能写一个字符,必须有内容 | 'a','中','国' | | 字符串常量 | 双引号包含,可以写多个字符,也可以不写 | "AAA","charles","" | | 布尔常量 | 只有两个值,非true即false | true,false | | 空常量 | 只有一个值 null | null | ### 案例 输出各种类型的常量: ```java public class ConstantDemo { public static void main(String[] args){ //输出整数常量 System.out.println(123); //输出小数常量 System.out.println(0.125); //输出字符常量 System.out.println('A'); //输出布尔常量 System.out.println(true); //输出字符串常量 System.out.println("你好Java"); } } ``` ## 变量和数据类型 ### 变量概述 变量:常量是固定不变的数据,那么在程序中可以变化的量称为变量。 > Java中要求一个变量每次只能保存一个数据,必须要明确保存的数据类型。 ### 常量和变量的运算 下面的程序有问题吗? ```java public static void main(String[] args){ byte b1=1; byte b2=2; byte b3=1 + 2; byte b4=b1 + b2; System.out.println(b3); System.out.println(b4); } ``` 分析: b3 = 1 + 2 , 1 和 2 是常量,为固定不变的数据,在编译的时候(编译器javac),已经确定了 1+2 的结果并没 有超过byte类型的取值范围,可以赋值给变量 b3 ,因此 b3=1 + 2 是正确的。 反之, b4 = b2 + b3 , b2 和 b3 是变量,变量的值是可能变化的,在编译的时候,编译器javac不确定b2+b3的结果是什 么,因此会将结果以int类型进行处理,所以int类型不能赋值给byte类型,因此编译失败。 ### 数据类型 #### 数据类型分类 Java的数据类型分为两大类: > - **基本数据类型**:包括 `整数` 、 `浮点数` 、 `字符` 、 `布尔` 。 > > - **引用数据类型**:包括 `字符串`、 `类` 、 `数组` 、 `接口` 。 > #### 数据类型的默认值 - 基本数据类型 | 数据类型 | 默认值 | | ------------------------------ | -------- | | 整数(byte,short,int,long) | 0 | | 浮点数(float,double) | 0.0 | | 字符(char) | '\u0000' | | 数组,类,接口 | false | - 引用数据类型 | 数据类型 | 默认值 | | -------------- | ------ | | 数组,类,接口 | null | #### 基本数据类型 四类八种基本数据类型: | 数据类型 | 关键字 | 内存占用(字节) | 取值范围 | | ------------ | ------------ | ---------------- | --------------------- | | 字节型 | byte | 1 | -128~127 | | 短整型 | short | 2 | -32768~32767 | | 整型 | int(默认) | 4 | -2^31~2^31 -1 | | 长整型 | long | 8 | -2^63~2^63 -1 | | 单精度浮点数 | float | 4 | 1.4013E-45~3.4028E+38 | | 双精度浮点数 | double(默认) | 8 | 4.9E-324~1.7977E+308 | | 字符型 | char | 2 | 0-65535 | | 布尔型 | boolean | 1 | true,false | #### 引用数据类型 ### 变量的定义 #### 格式 ``` 数据类型 变量名 = 数据值; ``` #### 案例 定义所有基本数据类型的变量,代码如下: ```java public class Variable { public static void main(String[] args){ //定义字节型变量 byte b = 100; System.out.println(b); //定义短整型变量 short s = 1000; System.out.println(s); //定义整型变量 int i = 123456; System.out.println(i); //定义长整型变量 long l = 12345678900L; System.out.println(l); //定义单精度浮点型变量 float f = 5.5F; System.out.println(f); //定义双精度浮点型变量 double d = 8.5; System.out.println(d); //定义布尔型变量 boolean bool = false; System.out.println(bool); //定义字符型变量 char c = 'A'; System.out.println(c); } } ``` ## 数据类型转换 ### 隐式转换(自动转换) **自动转换**:将 `取值范围小的类型` 自动提升为 `取值范围大的类型` 。 #### 转换规则: 范围小的类型向范围大的类型提升, `byte`、`short`、`char` 运算时直接提升为 `int` 。 > byte、short、char‐‐>int‐‐>long‐‐>float‐‐>double #### 案例: 一个 `int` 类型变量和一个 `byte` 类型变量进行加法运算, 结果会是什么数据类型? ```java 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` 类型,这就是出现了数据类型的自动类型转换现象。 ### 显式转换(强制转换) **强制类型转换:**将 `取值范围大的类型` 强制转换成 `取值范围小的类型` 。 比较而言,自动转换是Java自动执行的,而强制转换需要我们自己手动执行。 #### 转换格式: > 数据类型 变量名 = (数据类型)被转数据值; #### 案例: 当一个 `short` 类型与 1 相加,我们知道会类型提升,但是还想给结果赋值给short类型变量,就需要强制转换。 ```java public static void main(String[] args) { //short类型变量,内存中2个字节 short s = 1; /* 出现编译失败 s和1做运算的时候,1是int类型,s会被提升为int类型 s+1后的结果是int类型,将结果在赋值会short类型时发生错误 short内存2个字节,int类型4个字节 必须将int强制转成short才能完成赋值 */ s = s + 1;//编译失败 s = (short)(s+1);//编译成功 } ``` #### 特别注意: - 浮点转成整数,直接取消小数点,可能造成数据损失精度。 - int 强制转成 short 砍掉2个字节,可能造成数据丢失。 ### ASCII编码表 **编码表 :**就是将人类的文字和一个十进制数进行对应起来组成一张表格。 #### 需熟记的部分: | 字符 | 数值 | | :--: | :--: | | 0 | 48 | | 9 | 57 | | A | 65 | | Z | 90 | | a | 97 | | z | 122 | #### 特别注意: > 在char类型和int类型计算的过程中,char类型的字符先查询编码表,得到97,再和1求和,结果为98。char类型提升 为了int类型。char类型内存2个字节,int类型内存4个字节。 ## 运算符 ### 算术运算符 | 符号 | 意义 | | ------ | ---------------------------- | | + | 加法运算,字符串连接运算 | | - | 减法运算 | | * | 乘法运算 | | / | 除法运算 | | % | 取模运算,两个数字相除取余数 | | ++、-- | 自增自减运算 | #### 自增自减混合运算: - 和其他变量放在一起, 前++ 和 后++ 就产生了不同。 变量 前++ :变量a自己加1,将加1后的结果赋值给b,也就是说a先计算。a和b的结果都是2。 ```java public static void main(String[] args) { int a = 1; int b = ++a; System.out.println(a);//计算结果是2 System.out.println(b);//计算结果是2 } ``` 变量 后++ :变量a先把自己的值1,赋值给变量b,此时变量b的值就是1,变量a自己再加1。a的结果是2,b 的结果是1。 ```java public static void main(String[] args) { int a = 1; int b = a++; System.out.println(a);//计算结果是2 System.out.println(b);//计算结果是1 } ``` ### 赋值运算符 | 符号 | 意义 | | :--- | -------- | | = | 等于 | | += | 加等于 | | -= | 减等于 | | *= | 乘等于 | | /= | 除等于 | | %= | 取模等于 | #### +=符号的扩展 下面的程序有问题吗? ```java public static void main(String[] args){ short s = 1; s+=1; System.out.println(s); } ``` 分析: s += 1 逻辑上看作是 s = s + 1 计算结果被提升为int类型,再向short类型赋值时发生错误,因为不能将取值范围 大的类型赋值到取值范围小的类型。但是, s=s+1进行两次运算 , += 是一个运算符,只运算一次,并带有强制转换的特点, 也就是说 s += 1 就是 s = (short)(s + 1) ,因此程序没有问题编译通过,运行结果是2. ### 比较运算符 | 符号 | 意义 | | ---- | ------------------------------------------------------------ | | == | 比较符号两边数据是否相等,相等结果是true。 | | < | 比较符号左边的数据是否小于右边的数据,如果小于结果是true。 | | > | 比较符号左边的数据是否大于右边的数据,如果大于结果是true。 | | <= | 比较符号左边的数据是否小于或者等于右边的数据,如果小于结果是true。 | | >= | 比较符号左边的数据是否大于或者等于右边的数据,如果小于结果是true | | != | 不等于符号 ,如果符号两边的数据不相等,结果是true。 | ### 逻辑运算符 | 符号 | 意义 | | ---- | ------------------------------------------------------------ | | && | 1. 两边都是true,结果是true 2. 一边是false,结果是false 短路特点:符号左边是false,右边不再运算 | | \|\| | 1. 两边都是false,结果是false 2. 一边是true,结果是true 短路特点: 符号左边是true,右边不再运算 | | ! | 1. ! true 结果是false 2. ! false结果是true | ### 三元运算符(三目运算符) **格式:** ```java 数据类型 变量名 = 布尔类型表达式 ? 结果1 : 结果2 ``` **三元运算符计算方式:** - 布尔类型表达式结果是true,三元运算符整体结果为结果1,赋值给变量。 - 布尔类型表达式结果是false,三元运算符整体结果为结果2,赋值给变量。 #### 案例: ```java 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 } ``` ## 方法(函数或功能) ### 定义格式: ```java 修饰符 返回值类型 方法名 (参数列表){ 方法体 } ``` #### 案例: ```java public static void methodName() { System.out.println("这是一个方法"); } ``` ### 注意事项 方法定义注意事项: - 方法必须定义在一类中方法外 - 方法不能定义在另一个方法的里面 方法调用注意事项: - 方法在定义完毕后,方法不会自己运行,必须被调用才能执行 - 一般在main方法中调用 ## 数组 **数组概念:** 数组就是存储数据长度固定的容器,保证多个数据的数据类型要一致。 ### 数组的定义 **定义格式:** ```java 数组存储的数据类型[] 数组名 = new 数组存储的数据类型[长度]; ``` ```java 数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3...}; ``` ```java 数据类型[] 数组名 = {元素1,元素2,元素3...}; ``` #### 案例: 用三种格式定义数组 ```java public static void Array() { //定义可以存储3个整数的数组容器 int[] arr = new int[3]; //定义存储1,2,3,4,5整数的数组容器。 int[] arr = new int[]{1,2,3,4,5}; //定义存储1,2,3,4,5整数的数组容器(常用) int[] arr = {1,2,3,4,5}; } ``` ### 数组的访问 **访问格式:** ```java 数组名[索引] ``` > **索引**: 每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引 (index),可以通过数组的索引访问到数组中的元素。 #### 案例 利用索引访问数组 ```java public static void main(String[] args) { //定义存储int类型数组,赋值元素1,2,3,4,5 int[] arr = {1,2,3,4,5}; //为0索引元素赋值为6 arr[0] = 6; //获取数组0索引上的元素 int i = arr[0]; System.out.println(i); //直接输出数组0索引元素 System.out.println(arr[0]); } ``` ### 数组的遍历 ### 数组内存图 ## 面向对象 **概述**: Java语言是一种面向对象的程序设计语言,而面向对象思想是一种程序设计思想,我们在面向对象思想的指引下, 使用Java语言去设计、开发计算机程序。 这里的对象泛指现实中一切事物,每种事物都具备自己的属性和行为。面 向对象思想就是在计算机程序设计过程中,参照现实中事物,将事物的属性特征、行为特征抽象出来,描述成计算 机事件的设计思想。 它区别于面向过程思想,强调的是通过调用对象的行为来实现功能,而不是自己一步一步的去 操作实现。 **举例:** 把大象放进冰箱: 洗衣服: - 面向过程:把衣服脱下来-->找一个盆-->放点洗衣粉-->加点水-->浸泡10分钟-->揉一揉-->清洗衣服-->拧干-->晾 起来 - 面向对象:把衣服脱下来-->打开全自动洗衣机-->扔衣服-->按钮-->晾起来 **区别:** - 面向过程:强调步骤。 - 面向对象:强调对象,这里的对象就是洗衣机 > 面向对象思想是一种更符合我们思考习惯的思想,它可以将复杂的事情简单化,并将我们从执行者变成了指挥者。 面向对象的语言中,包含了三大基本特征,即封装、继承和多态。 ## 类与对象 ### 类的定义 定义格式: ```java public class ClassName { //成员变量 //成员方法 } ``` **案例**:定义一个学生类 ```java public class Student { //成员变量 String name;//姓名 int age;//年龄 //成员方法 //学习的方法 public void study() { System.out.println("好好学习,天天向上"); } //吃饭的方法 public void eat() { System.out.println("学习饿了要吃饭"); } } ``` ### 对象的定义 创建对象的格式: ```java 类名 对象名 = new 类名(); ``` 访问对象中的成员的格式: ```java 对象名.成员变量; 对象名.成员方法(); ``` **案例:**利用上一个案例定义的学生类,实例化对象并访问对象中的成员 ```java public class Test { public static void main(String[] args) { //创建对象格式:类名 对象名 = new 类名(); Student s = new Student(); System.out.println("s:"+s); //直接输出成员变量值 System.out.println("姓名:"+s.name); //null System.out.println("年龄:"+s.age); //0 System.out.println("‐‐‐‐‐‐‐‐‐‐"); //给成员变量赋值 s.name = "charles"; s.age = 18; //再次输出成员变量的值 System.out.println("姓名:"+s.name);//charles System.out.println("年龄:"+s.age);//18 //调用成员方法 s.study(); // "好好学习,天天向上" s.eat(); // "学习饿了要吃饭" } } ``` ### 对象的内存图 ## 封装性 将`属性`隐藏起来,若需要访问某个`属性`,提供`公共方法`对其访问。 使用 `private` 关键字来修饰成员变量。 对需要访问的`成员变量`,提供对应的一对 `getXxx` 方法 、 `setXxx` 方法。 ### private - private是一个权限修饰符,代表最小权限。 - 可以修饰成员变量和成员方法。 - 被private修饰后的成员变量和成员方法,只在本类中才能访问。 **格式:** ```java private 数据类型 变量名 ; ``` **案例**:使用private关键字定义学生类 ```java public class Student { private String name; private int age; public void setName(String n) { name = n; } public String getName() { return name; } public void setAge(int a) { age = a; } public int getAge() { return age; } } ``` ### this - this代表所在类的当前对象的引用(地址值),即对象自己的引用。 **格式:** ```java this.成员变量名; ``` **案例:**使用 this 修饰方法中的变量,解决参数和成员变量字段相同导致的二义性问题 ```java public class Student { private String name; private int age; public void setName(String name) { //name = name; //编译器认为name为参数中的name,造成无效赋值 this.name = name; } public String getName() { return name; } public void setAge(int age) { //age = age; this.age = age; } public int getAge() { return age; } } ``` ## 继承性 ### 继承的定义: **继承**::就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接 访问父类中的**非私有**的属性和行为。 **继承格式:** 通过 extends 关键字,可以声明一个子类继承另外一个父类 ```java class 父类 { ... } class 子类 extends 父类 { ... } ``` **特点:** - 提高代码的复用性。 - 类与类之间产生了关系,是多态的前提。 - Java只支持单继承,不支持多继承。 - Java支持多层继承(继承体系)。 - 子类和父类是一种相对的概念。 ### super - 子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用 `super` 关键字 **格式:** ```java super.父类成员变量名 ``` **案例:**使用super关键字访问父类重名成员 ```java class Father { // Father中的成员变量。 int num = 5; } class Son extends Father { // Son中的成员变量 int num = 6; public void show() { //访问父类中的num System.out.println("Father num=" + super.num); //访问子类中的num System.out.println("Son num=" + this.num); } } ``` ### Override - 如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做**方法重写** (Override)。 - 子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效 果,也称为重写或者复写。**声明不变,重新实现**。 **案例:**子类重写父类的成员方法 ```java class Father { public void show() { System.out.println("Father show"); } } class Son extends Father { //子类重写了父类的show方法 public void show() { System.out.println("Son show"); } } public class Test{ public static void main(String[] args) { Son s = new Son(); // 子类中有show方法,只执行重写后的show方法 s.show(); // Son show } } ``` **特别注意:** - 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。 - 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。 ### abstract **使用格式:** 抽象方法: ```java 修饰符 abstract 返回值类型 方法名 (参数列表); ``` 抽象类: ```java abstract class 类名 { } ``` **代码举例:** ```java //抽象方法: public abstract void method(); //抽象类: public abstract class ClassName { } ``` **案例:** 定义动物抽象类,实例化猫运行抽象类中的成员方法 ```java public class Cat extends Animal { public void run (){ System.out.println("小猫在墙头走~~~"); } } public class Test { public static void main(String[] args) { // 创建子类对象 Cat c = new Cat(); // 调用run方法 c.run(); } } ``` **注意事项:** - 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。 - 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。 - 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。 - 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象 类。 ## 多态性 - 当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写 后方法。 - 利用父类指针指向子类对象 ### 多态的定义: **多态:** 是指同一行为,具有多个不同表现形式。 **多态体现的格式:** ```java 父类类型 变量名 = new 子类对象; 变量名.方法名(); ``` **特点:** - 实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展 性与便利 ### **案例:** 定义父类: ```java public abstract class Animal { public abstract void eat(); } ``` 定义子类: ```java class Cat extends Animal { public void eat() { System.out.println("吃鱼"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨头"); } } ``` 定义测试类: ```java public class Test { public static void main(String[] args) { // 多态形式,创建对象 Cat c = new Cat(); Dog d = new Dog(); // 调用showCatEat showCatEat(c); // 调用showDogEat showDogEat(d); /* 以上两个方法, 均可以被showAnimalEat(Animal a)方法所替代 而执行效果一致 */ showAnimalEat(c); showAnimalEat(d); } public static void showCatEat (Cat c){ c.eat(); } public static void showDogEat (Dog d){ d.eat(); } public static void showAnimalEat (Animal a){ a.eat(); } } ``` ### 多态的转型 - **当父类引用指向一个子类对象时,便是向上转型。** - **一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。** #### 向上转型 **向上转型:**多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。 当父类引用指向一个子类对象时,便是向上转型。 **使用格式:** ```java 父类类型 变量名 = new 子类类型(); 如:Animal a = new Cat(); ``` #### 向下转型 **向下转型:**父类类型向子类类型向下转换的过程,这个过程是强制的。 **使用格式:** ```java 子类类型 变量名 = (子类类型) 父类变量名; 如:Cat c =(Cat) a; ``` #### 转型异常 转型的过程中,一不小心就会遇到这样的问题,请看如下代码: ```java public class Test { public static void main(String[] args) { // 向上转型 Animal a = new Cat(); a.eat(); // 调用的是 Cat 的 eat // 向下转型 Dog d = (Dog)a; d.watchHouse(); // 调用的是 Dog 的 watchHouse 【运行报错】 } } ``` 这段代码可以通过编译,但是运行时,却报出了 `ClassCastException` ,类型转换异常 这两个类型并没有任何继承关系,不符合类型转换的定义 为了避免`ClassCastException`的发生,Java提供了 `instanceof` 关键字,给引用变量做类型的校验,格式如下: ```java 变量名 instanceof 数据类型 ``` 如果变量属于该数据类型,返回true。 如果变量不属于该数据类型,返回false。 所以,转换前,我们最好先做一个判断,代码如下: ```java public class Test { public static void main(String[] args) { // 向上转型 Animal a = new Cat(); a.eat(); // 调用的是 Cat 的 eat // 向下转型 if (a instanceof Cat){ Cat c = (Cat)a; c.catchMouse(); // 调用的是 Cat 的 catchMouse } else if (a instanceof Dog){ Dog d = (Dog)a; d.watchHouse(); // 调用的是 Dog 的 watchHouse } } } ``` ## 接口

你可能感兴趣的:(Java)