Java基础知识复习01:从基础知识---面向对象(后续会更新)

在我的资源里有:pdf对应的完整内容需要的可以自行下载,无偿分享给大家

一、快捷键

Alt + / :

1)在java类中,要输出main方法,只要输入main然后用此快捷键按回车即可;

2)要输出System.out.println(),你只需输入syso然后用此快捷键按回车即可;

3)再比如你要覆盖父类的toString()方法,你只需输入to然后用此快捷键按回车;

4)再比如你要用一个没有import的类(比如Calendar),你只需输入Ca然后用此快捷键即可用上下键选择;再比如你要生成某个field的get,set方法,你只需输入get然后用此快捷键生成(默认为public);

(2)在jsp页面中可用此提示输入标签(标签内提示标签属性)

(3)在xml中也可用此快捷键。

alt+shift+j给函数添加doc注释

Ctrl + Shift + T : 打开Open Type 查找类文件

Ctrl + Shift + F4 : 关闭所在打开的窗口

Ctrl + O : Open declarations

Ctrl + E : 打开编辑器(切换窗口)

Ctrl + / : 注释本行

Alt + Shift + R : 重命名

Alt + Shift + L : 抽取本地变量

Alt + Shift + M : 抽取方法

F3 : Open Declaration

Ctrl + D : 删除本行

Ctrl + SHIFT + F : 整形

Ctrl + Alt + ↓(↑) : 向下(上)复制本行

Alt + ↓(↑) : 向下(上)移动本行

 

文档注释以 /** 开始,以*/ 结束

二、开发环境搭建

JDK简单理解就是Java开发工具包,JVM也就是常常听到Java虚拟机。JDK是面向开发者的,JRE是面向使用JAVA程序的用户。

bin:最主要的是编译器(javac.exe)

include:java和JVM交互用的头文件

lib:类库

jre:java运行环境

 

2.1java虚拟机--JVM

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。

引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。

 

三、基础概念

位(bit):一个数字0或者一个数字1,代表一位

字节(Byte):每逢8位是一个字节,这是数据额存储的最小单位。

1Byte=8bit;1KB=1024Byte;1MB=1024K

3.1 关键字特性

1.完全小写的字母。

2.在增强版的记事本当中有特殊颜色。

 

3.2 标识符

所有标识符必须以字母(a-z,A-Z)美元符($)下划线(_)开始

首字符后可以用字母(a-z,A-Z)美元符($)下划线(_)或者数字

 

注意:1)不能使用变量名

2)不能使用关键字

3)大小写敏感的不能写错

 

命名规则:

类名规范:首字母大写,后面每个单词首字母大写。

变量名规范:首字母小写,后面每个单词首字母大写。

方法名规范:同变量名。

 

Java中标识符的命名约定:

小驼峰式命名:变量名、方法名

首字母小写,从第二个单词开始每个单词的首字母大写。

大驼峰式命名:类名

每个单词的首字母都大写。

另外,标识符的命名最好可以做到见名知意

 

3.3 常量

字符串型:用双引号 " " 引起来的部分。    

整型:无小数点。

浮点型:有小数点

字符:用单引号 ' '         

布尔类型:只有量中取值。true或false

空常量:NULL,无任何数据。

 

强制转换:

数据类型A 变量a=(数据类型A)变量b

常量:指的是取值不可变的变量

使用final修饰:final 数据类型 变量名=值;

static作用于成员变量用来表示只保存一份副本,而final的作用是用来保证变量不可变。

 

变量的使用;

1.作为主方法内的一个普通数据

2.定义一个类的属性

类是一种事物的描述

如何描述:特征(属性)与功能(方法)

 

public class demo01 {
	//定义demo01类的属性,属性名:age
	static int age=13;
	public static void main (String[] args) {
		System.out.println("helloword");
	}
}

在写类中:如何访问属性值?

类名.属性(Byte.MAX_VALUE)来访问

 

注意事项:

1. 在同一对花括号中,变量名不能重复。

2. 变量在使用之前,必须初始化(赋值)。

3. 定义long类型的变量时,需要在整数的后面加L(大小写均可,建议大写)。因为整数默认是int类型,整数太

大可能超出int范围。

4. 定义flfloat类型的变量时,需要在小数的后面加F(大小写均可,建议大写)。因为浮点数的默认类型是

double, double的取值范围是大于flfloat的,类型不兼容。

 

3.4数据类型

1、基本数据类型:

1字节=8位

8位:Byte(字节型)  16位:short(短整型)、char(字符型)        

32位:int(整型)、float(单精度型/浮点型)    

64位:long(长整型)、double(双精度型)  最后一个:boolean(布尔类型)

整数型:Byte、short、int、long

浮点型:float、double

字符型:char

布尔型:boolean

类型转换:char-int-long-float-double

 

2、引用数据类型

字符串、数组、类、接口、Lambda

 

3、注意事项

1)字符串不是基本类型,二是引用型。

2)浮点型可能只是一个近似值,并非精确的值。

3)数据范围与字节数不一定相关。

4)浮点数当中默认类型是double,如果一定要使用float类型,需加上一个后缀F。

如果是整数,默认为int类型,如果一定要使用long类型,需要加上一个后缀L。

 

3.5 变量和数据类型

数据类型 变量名称=数据值; int a=2;

自动类型转换(隐式)

1.特点:代码不需要进行特殊处理,自动完成。

2.规则:数据范围从小到大。int --->long

double num = 10; // 将int类型的10直接赋值给double类型 System.out.println(num); // 输出10.0

强制类型转换(显式):不推荐使用,可能导致精度损失、数据溢出;byte/short/char在运算时都会首先升级为int类型在计算;boolean类型不能发生数据类型转换

1.特点:代码需要进行特殊的格式处理,自动完成。

2.规则:范围小的类型 范围小的变量名 =(范围小的类型)原本范围大的数据。

double num1 = 5.5; int num2 = (int) num1; // 将double类型的num1强制转换为int类型 System.out.println(num2); // 输出5(小数位直接舍弃)

 

3.6运算符

1、算术运算符

/: 取整除 | 返回除法的整数部分(商) 9 // 2 输出结果 4。

%:取余数 | 返回除法的余数 9 % 2 = 1。

**:幂,又称次方、乘方,2 ** 3 = 8 。

++在非单独使用:

++在后: 会现将变量原本所记录的值取出来进行操作, 然后再完成自身+1的运算。

++在前: 先完成自身+1的运算, 然后再进行赋值。

++/--在单独使用时无区别。

int x = 4;
//括号1 : 现将x原本记录的4取出来  --> 4
//括号2 : 将上一次变化后的5, 再进行++在前的运算 --> 6
//括号3 : 60
int y = (x++)+(++x)+(x*10);  // 70

 

2、赋值运算符

基本赋值运算符:就一个=

符合运算符:+= -= *= /= %=

eg: a+=1 -->a=a+1

只有变量才能使用赋值运算符,常量不能进行复制。

复合赋值运算符其中隐含了一个强制类型转换

 

3、比较运算符

== < > <= >= !=

结果一定是boolean值,成立就是true,不成立就是false

如果进行多次判断,不能连者写

 

4、逻辑运算符:

&逻辑与:a&b,a和b都是true,结果为true,否则为false

|逻辑或:a|b,a和b都是false,结果为false,否则为true

^逻辑异或:a^b,a和b结果不同为true,相同为false

!逻辑非:!a,结果和a的结果正好相反

&&短路与:作用和&相同,但是有短路效果

||短路或:作用和|相同,但是有短路效果

 

& 与: 与--> 并且--> 结论: 左边两边, 必须同时为true, 结果才为true换句话说, 遇false, 则false.

int i = 10;

System.out.println(i > 5 & i < 20);

| : 或--> 或者--> 结论: 左右两边, 只要有一个为true, 结果就为true换句话说, 遇true, 则true。

&&双与: 短路与 左边返回false的时候, 右边就不再执行了。

左边返回为true, 右边依旧执行。

|| : 至少一个是true就是true;全为false时才为false。

!  : 非--> 取反 --> 特点: 非两次, 结果不变。

^  异或 : 相同为false, 不同为true。

特点 :

一个数, 被另外一个数, 异或两次, 该数本身不变10 ^ 6 ^ 6

 

&&和& 有什么区别?

& : 无论左边返回的结果是true还是false, 右边都必须执行。

&& : 全为true,才为true;否者为false。

int a=3;

2<a<4

||和| 有什么区别?

|| :一旦判断左边是true之后, 右边就不参与运算了 | :不管左边是true还是false, 右边都参与运算

5、三元(三目)运算符: 

数据类型 变量名称=条件判断(比较表达式) ? 值1 : 值2;

    看比较表达式返回的结果是true还是false

        true : 值1;

        false : 值2;

int i = 10; int i2 = 20; boolean flag = (i == i2) ? true : false;

6、扫描器:

1、导包。Scanner 类在java.util包下,所以需要将该类导入。导包的语句需要定义在类的上面。

import java.util.Scanner;

2、创建Scanner对象。

Scanner sc = new Scanner(System.in); // 创建Scanner对象,sc表示变量名,其他均不可变

3、接收数据

int i = sc.nextInt(); // 表示将键盘录入的值作为int数返回。

扫描器是一种输入

1)引入扫描器类

import java.util.Scanner;

2)新建扫描器对象

Scanner 对象名=new Scanner(System.in)

3)扫描数据"理解为输入一个数据"

扫描整数

扫描器对象.nextInt();

扫描小数

扫描器对象.nextDouble();

扫描字符串

扫描器对象.next();

package day01;
import java.util.Scanner;
public class t2 {
	public static void main(String[] args) {
		Scanner t2=new Scanner(System.in);
		System.out.println("请输入一个整数");
		int x=t2.nextInt();//输入一个整数
		System.out.println("扫描的整数为"+x);//输出整数x
}
}
import java.util.Scanner;
public class t8 {

	public static void main(String[] args) {
		System.out.println("请输入你要判断的车速");
		int speed = new Scanner(System.in).nextInt();
		//在句尾用alt+shift+l  快速接受变量返回值
		if(speed>100&&speed<120) {
			System.out.println("超速");
		}else if(speed>120) {
			System.out.println("警告");
		}}}

 

练习1:

要求:扫描一个字符串,表示商品名称;扫描一个小数,表示商品单价;扫描一个整数,表示商品数量;输出商品总价;再次扫描所付金额,输出找零数目。

import java.util.Scanner;
public class t3 {
public static void main(String[] args) {
		Scanner t3=new Scanner(System.in);
		String z=t3.next();
		System.out.println("商品名称"+z);
		double y=t3.nextDouble();
		System.out.println("商品单价"+y);
		int x=t3.nextInt();
		System.out.println("商品数量"+x);
		System.out.println("商品总价"+x*y);
		double zhichu=t3.nextDouble();
		System.out.println("付款总额"+zhichu);
		double s=zhichu-x*y;
		System.out.println("找零"+s);}}

 

首先Random是随机生成数用法,介绍一下:

 

概述:

Random类似Scanner,也是Java提供好的API,内部提供了产生随机数的功能

API后续课程详细讲解,现在可以简单理解为Java已经写好的代码

使用步骤:

1. 导入包 import java.util.Random;

2. 创建对象 Random r = new Random();

3. 产生随机数 int num = r.nextInt(10);

解释: 10代表的是一个范围,如果括号写10,产生的随机数就是0-9,括号写20,参数的随机数则是0- 19

 

四、方法和结构

 

4.1 方法method

定义一个方法的格式:

public static void 方法名称() { 方法体 } 如何调用方法,格式: 方法名称();

注意事项:

1.方法定义的先后顺序无所谓

2.方法的定义不能产生嵌套包含关系

3.方法定义好了之后,不会执行的。如果要想执行,一定要进行方法的调用。

public static void main(String[] args) {
              cook();
	}
public static void cook() {
       System.out.println("洗菜");
       System.out.println("切菜")
       System.out.println("煮菜")
	}

 

4.2 判断语句

1) if(){

}

else

 

2) switch

switch (表达式) { case 1: 语句体1; break; case 2: 语句体2; break; ... default: 语句体n+1; break; }

执行流程:

首先计算出表达式的值

其次,和case依次比较,一旦有对应的值,就会执行相应的语句,在执行的过程中,遇到break就会结束。

最后,如果所有的case都和表达式的值不匹配,就会执行default语句体部分,然后程序结束掉。

 

3)for循环

for (初始化语句;条件判断语句;条件控制语句) { 循环体语句; }

格式解释:

初始化语句: 用于表示循环开启时的起始状态,简单说就是循环开始的时候什么样

条件判断语句:用于表示循环反复执行的条件,简单说就是判断循环是否能一直执行下去

循环体语句: 用于表示循环反复执行的内容,简单说就是循环反复执行的事情

条件控制语句:用于表示循环执行中每次变化的内容,简单说就是控制循环是否能执行下去

执行流程:

①执行初始化语句

②执行条件判断语句,看其结果是true还是false

如果是false,循环结束

如果是true,继续执行

③执行循环体语句

④执行条件控制语句

⑤回到②继续

 

4)while循环

初始化语句; while (条件判断语句) { 循环体语句; 条件控制语句; }

while循环执行流程:

①执行初始化语句

②执行条件判断语句,看其结果是true还是false

如果是false,循环结束

如果是true,继续执行

③执行循环体语句

④执行条件控制语句

⑤回到②继续

 

初始化语句; do { 循环体语句; 条件控制语句; }while(条件判断语句);

执行流程:

① 执行初始化语句

② 执行循环体语句

③ 执行条件控制语句

④ 执行条件判断语句,看其结果是true还是false

如果是false,循环结束

如果是true,继续执行

⑤ 回到②继续

三种循环的区别

for循环和while循环先判断条件是否成立,然后决定是否执行循环体(先判断后执行)

do...while循环先执行一次循环体,然后判断条件是否成立,是否继续执行循环体(先执行后判断) for循环和while的区别

条件控制语句所控制的自增变量,因为归属for循环的语法结构中,在for循环结束后,就不能再次被访问到了

条件控制语句所控制的自增变量,对于while循环来说不归属其语法结构中,在while循环结束后,该变量还可以继续使用

 

死循环(无限循环)的三种格式

1. for(;;){}

2. while(true){}

3. do {} while(true);

 

跳转控制语句(break)

跳出循环,结束循环

跳转控制语句(continue)

跳过本次循环,继续下次循环

注意: continue只能在循环中进行使用!

 

break两种用法:

1.可以用在switch语句当中,一旦执行,整个switch语句立即结束。

2.还可以用在循环语句当中,一旦执行,整个循环语句立即结束,打断循环。

 

continue控制语句:一旦执行,立刻跳过当前次循环剩余内容,马上开始下一次循环。

 

循环的选择:

凡是次数确定的场景多用for循环;否则多用while循环。

 

注意事项:

1.多个case后面的数值不可以重复。

2.switch后面的小括号当中只能是下列数据类型:

基本数据类型:byte/short/char/int

引用数据类型:String字符串/enum枚举

3.switch语句格式可以很灵活:前后顺序可以颠倒,而且break语句还可以省略

 

5)死循环:永远停不下。强制停止ctrl+c

死循环标准格式:

while(true){

循环体;

}

注意事项:

总结:

1. print为一般输出,同样不能保留精度格式转化,也不能换行输出

2.printf常用于格式转换,但需要注意不是换行输出,只用于精度转换

3.println为换行输出,不能用于格式转换

/*随机数游戏*/
import java.util.Random;
import java.util.Scanner;
public class Suijishu {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Random random = new Random();
        int relNumber = random.nextInt(100) + 1;
        System.out.println("系统会随机产生一个1至100的整数,请猜出这个数!");
        System.out.println("请输入您猜的数字:");
        Scanner reader = new Scanner(System.in);
        int x = reader.nextInt();
        while (x != relNumber) {
            if (x > relNumber) {
                System.out.println("猜大了,请重新尝试");
                x = reader.nextInt();
            } else {
                System.out.println("猜小了,请重新尝试");
                x = reader.nextInt();
            }
        }
        System.out.println("恭喜您,猜对了!");
    }
}

 

五、方法提升

5.1、定义方法完整格式:

修饰符 返回值类型 方法名称(参数类型 参数名称,......){

方法体

return返回值;

}

public static int sum(int a , int b) {
        System.out.println("方法执行");
        int result=a+b;
        return result;
    }

 

修饰符:现阶段固定写法,public static

返回值类型:也就是方法最终产生的数据结果是什么类型

方法名称:方法的名字,规则和变量一样,小驼峰

小驼峰命名规则:第一个单词小写,其他单词首字母大写 写法如:myFirstName 大驼峰命名规则:第一个单词首字母大写,其他单词首字母也大写 写法如:MyFirstName

 

参数类型:进入方法的数据是什么类型

参数名称:进入方法的数据对应的变量名称

 

PS:参数如果有多个,是用逗号进行分割

方法体:方法需要做的事情。若干行代码

return:两个作用,第一个是停止当前方法;第二个是将后面的返回值还给调用出

返回值:也就是方法执行后最终产生的数据结果

public class define {
    public static void main(String[] args) {
        sum(2,3);
        System.out.println();
        System.out.println(sum(1,3));
    }
    public static int sum(int a , int b) {
        System.out.println("方法执行");
        int result=a+b;
        return result;
    }}

 

注意:return后面的“返回值”,必须和方法名称前面的“返回值类型”,保持对应

 

定义一个两个int数字相加的方法。

三要素

{返回值类型:int 方法名称:sum 参数列表:int 啊,int b}

 

方法的三种调用格式:

1.单独调用:方法名称(参数);

sum(2,3); System.out.println();

2.打印调用:System.out.println(方法名称(参数));

System.out.println(sum(1,3));

3.赋值调用:数据类型 变量名称=方法名称(参数);

int number=sum(1,2);

import java.util.Scanner;
public class t3 {
    public static void main(String[] args) {
        System.out.println("请输入第一个数字");
        int x=new Scanner(System.in).nextInt();
        System.out.println("请输入第二个数字");
        int y=new Scanner(System.in).nextInt();
        System.out.println("请输入运算符");
        int q=new Scanner(System.in).nextInt();
        if(q==1){
            System.out.println(add(x,y));
        }else if(q==2){
            System.out.println(chengfa(x,y));
        }else if(q==3){
            System.out.println(jianfa(x,y));
        }
    }
    public static int  add(int a,int b) {
        int sum=a+b;
        return sum;
    }
    public static int  chengfa(int a,int b) {
        int cf=a*b;
        return cf;
    }
    public static int  jianfa(int a,int b) {
        int jf=a-b;
        return jf;
    }
}

5.2、有参和无参

有参数:小括号当中有内容,当一个方法需要一些数据条件,才能完成任务的时候,就是有参数。

例如:两个数相加相乘需要知道具体参数。

无参数:小括号当中留空。一个方法不需要任何数据条件,自己就能独立完成任务。就是无参。

例如:打印字符。

 

注意事项:

1.方法应该定义在类当中,但是不能在方法当中再定义方法。不能嵌套。

2.方法定义的前后顺序无所谓。

3.方法定义之后不会执行,如果希望执行,一定要调用:单独调用、打印调用、赋值调用。

4.如果方法有返回值那么必须写上“return 返回值;”不能没有。

5.return后面的返回值数据,必须和方法的返回值类型,对应起来。

6.对于一个void没有返回值,不能写return后面返回值,只能写return自己。

7.对于void方法当中最后一行的return可以省略不写。

8.一个方法当中可以有多个return语句,但是必须保证同时只有一个会被执行到,两个return不能连写。

 

1. 形参:方法定义中的参数

等同于变量定义格式,例如:int number

public static void getMax(int a, int b)

2. 实参:方法调用中的参数

等同于使用变量或常量,例如: 10 number

int a = 10; int b = 20;

public class MethodTest { 
public static void main(String[] args) { 
//在main()方法中调用定义好的方法(使用常量) 
getMax(10,20); 
//调用方法的时候,人家要几个,你就给几个,人家要什么类型的,你就给什么类型的 
//getMax(30); 
//getMax(10.0,20.0); 
//在main()方法中调用定义好的方法(使用变量) 
int a = 10; 
int b = 20; 
getMax(a, b); } 
//定义一个方法,用于打印两个数字中的较大数,例如getMax() 
//为方法定义两个参数,用于接收两个数字 
public static void getMax(int a, int b) { 
//使用分支语句分两种情况对两个数字的大小关系进行处理 
if(a > b) { 
System.out.println(a); 
} else { 
System.out.println(b); } } }

5.3、方法的重载(overload)

方法重载概念 方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载

多个方法在同一个类中

多个方法具有相同的方法名

多个方法的参数不相同,类型不同或者数量不同

注意:

重载仅对应方法的定义,与方法的调用无关,调用方式参照标准格式

重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载

 

多个方法的名称一样,但是参数列表不一样。

好处:只需要记住唯一一个方法名称,就可以实现类似的多个功能。

方法重载与下列因素有关:

1.参数个数不同

2.参数类型不同

3.参数多类型顺序不同

方法重载与下列因素无关:

1.与参数的名称无关

2.与方法的返回值类型无关

方法名称(参数类型(参数列表) 参数名称,......)

public class t13 {
        public static void main(String[] args) {
//调用方法
            System.out.println(compare(10, 10));
            System.out.println(compare((byte) 10, (byte) 20));
            System.out.println(compare((short) 10, (short) 20));
            System.out.println(compare(10L, 20L));
        }
        //int
        public static boolean compare(int a, int b) {
            System.out.println("int:");
            return a == b;
        }
        //byte
        public static boolean compare(byte a, byte b) {
            System.out.println("byte:");
            return a == b;
        }
        //short
        public static boolean compare(short a, short b) {
            System.out.println("short:");
            return a == b;
        }
        //long
        public static boolean compare(long a, long b) {
            System.out.println("long:");
            return a == b;
        }
    }

六、数组

6.1、数组的定义格式

1、数组的概念:是一种容器,可以同时存放多个数据值

 

2、数组的特点:

1.数组是一种引用数据类型。

2.数组当中的多个数据,类型必须统一。

3.数组的长度在程序运行期间不可改变。

 

3、数组的初始化:在内存当中创建一个数组,并且向其中赋予一些默认值。

 

两种常见的初始化方式:

1.动态初始化(指定长度):在创建数组的时候,直接给定数组当中的数据元素个数。

格式:

数据类型【】 数组名称=new 数据类型【数组长度】;

int[] A=new int[300];

 

//动态创建 int a[]=new int[5]; //静态创建 int b[]=new int[]{1,2,3,4,5,6} ; int b[]={1,2,3,4,5,6};

解析含义:

左侧数据类型:也就是数组当中的保存的数据,全都是统一的什么类型。

左侧的中括号:代表我是一个数组。

左侧数组名称:给数组取一个名字。

 

右侧的new:代表创建数组的动作。

右侧数据类型:必须和左边的数据类型保持一致。

右侧中括号的长度:也就是数组当中,到底可以保存多少个数据,是一个int数字。

 

2.静态初始化(指定内容):在创建数组的时候,不直接给定数据个数多少,而是直接将具体的数据内容进行指定。

基本格式:数据类型【】 数组名称=new 数据类型【】{元素1,元素2,。。。。。};

int[] A=new int[]{1,2,3};

省略格式:数据类型【】 数组名称={元素1,元素2,。。。。。};

int[] A={1,2,3};

 

1)虽然静态初始化没有直接告诉长度,但是根据大括号里面的元素内容,也可以自动推算出来长度。

2)静态初始化标准格式可以拆分成两个步骤。

3)动态初始化也可以拆分成两个步骤。

4)静态初始化一旦使用省略格式,就不能拆分成两个步骤了

使用建议:

如果不确定数组当中的具体内容,用动态初始化,否者,已经确定了具体内容,用静态初始化。

 

4、数组访问

访问数组的元素的格式:数组名称【索引值】

索引值,就是一个int数字,代表数组当中元素的编号。

注意:索引值从0开始,一直到“数组的长度-1”为止

使用动态初始化数组的时候,其中的元素将会自动拥有一个默认值,规则如下:

如果是整数类型,那么默认为0;

如果是浮点类型,那么默认为0.0;

如果是字符类型,那么默认为"\u0000";

如果是布尔类型,那么默认为false;

如果是引用类型,那么默认为null;

注意事项:静态初始化其实也有默认值的过程,只不过系统自动马上将默认值替换成为大括号当中的具体数值。

 

6.2、数组的内存图

内存划分为五部分:

1.栈(stack):存放的都是方法中的局部变量。方法的运行一定要在栈当中运行。

局部变量:方法的参数,或者是方法{ }内部变量。

作用域:一旦超出作用域,立刻从栈内存当中消失。

2.堆(heap):凡是new出来的东西,都在堆当中。

堆内存里面的东西都有一个地址值:16进制

堆内存里面的数据,都幽默认值。

规则:

如果是整数类型,那么默认为0;

如果是浮点类型,那么默认为0.0;

如果是字符类型,那么默认为"\u0000";

如果是布尔类型,那么默认为false;

如果是引用类型,那么默认为null;

 

3.方法区(Method Area):存储 .class相关信息,包含方法的信息。

4.本地方法栈(Native Method Stack):与操作系统相关。

5.寄存器(pc Register):与CPU相关。

 

寄存器:给CPU使用,和我们开发无关。

本地方法栈:JVM在使用操作系统功能的时候使用,和我们开发无关。

方法区:存储可以运行的class文件。

堆内存:存储对象或者数组,new来创建的,都存储在堆内存。

方法栈:方法运行时使用的内存,比如main方法运行,进入方法栈中执行。

一、单个数组

 

 

 

 

 

 

 

 

 

二、多个数组

 

 

 

 

 

三、

 

 

 

6.3、数组异常

数组的索引编号从0开始,一直到“数组的长度为-1”为止。

 

如果访问数组的元素的时候,索引编号并不存在,那么将会发生数组索引越界异常。

原因:索引编号写错。

解决:修改成为存在的正确索引编号。

 

所有的引用类型变量,都可以赋值为一个null值。但是代表其中什么都没有。

数组必须进行new 初始化才能使用其中元素。

如果只是赋值了一个null,没有进行new创建。

那么将会发生:空指针异常 NullPointerException

 

原因:忘了new

解决:补上new

int [] array=null; array=new int[3];

 

6.4数组运算

 

1、如何获取数组长度,格式:

数组名称.length

 

这将会得到一个int数字。代表数组长度。

int[] arr={}; int len=arr.length; System.out.println(len);

数组一旦创建,程序运行期间,长度不可改变。

 

 

 

 

 

在Java中,

length方法用于获取数组的长度。

int[] arr = new int[10]; System.out.println(arr.length);

 

而length()用于获取String字符串中字符的个数。

String str = "HelloJava"; System.out.println(str.length());

//String字符串的方法和String[]的属性的区别
int a[]=new int[]{1,2,3,4,5,7,6,45,54,5};//length属性
System.out.println(a.length);

String b="ABSHJDBG";//length方法
System.out.println(b.length());

 

2、遍历输出:

说的是对数组当中的每一个元素进行逐一、挨个儿处理。默认的处理方式就是打印输出。

求反数:

 

 

 

 

 

从小到大遍历

Arrays.sort(a); //自动遍历:从小到大输出

System.out.println(Arrays.toString(a)); //遍历输出

 

//从小到大遍历
import java.util.Arrays;
public class t6 {
    public static void main(String[] args) {
        int a[]={1,2,35,3,23,656,121,45};

        Arrays.sort(a);//自动遍历:从小到大输出
        System.out.println(Arrays.toString(a));//遍历输出
    }
}

方法参数传递引用类型

结论: 对于引用类型的参数,形式参数的改变,影响实际参数的值

结论依据: 引用数据类型的传参,传入的是地址值,内存中会造成两个引用指向同一个内存的效果,所以即使方法 弹栈,堆内存中的数据也已经是改变后的结果

public class t1 {
    public static void main(String[] args) {
        int[] a={10,20,30};
        System.out.println("第一次输出"+a[1]);
        change(a);//先到int[] a={10,20,30};再到change(int[] a);最后改变a[1]输出
        System.out.println("第二次输出"+a[1]);
    }
    public static void change(int[] a){
        a[1]=200;
    }
}

3、java split()的用法:

Java中split主要用于分隔字符串。

具体分析如下:

1、如果用“.”作为分隔的话,必须是如下写法,String.split("\\."),这样才能正确的分隔开,不能用String.split(".")。

2、如果用“|”作为分隔的话,必须是如下写法,String.split("\\|"),这样才能正确的分隔开,不能用String.split("|"),“.”和“|”都是转义字符,必须得加"\\"。

3、如果在一个字符串中有多个分隔符,可以用“|”作为连字符,比如,“acount=? and uu =? or n=?”,把三个都分隔出来,可以用String.split("and|or")。

 

String a1="12341`1234`5456";
String[] a2=a1.split("\\`");
System.out.println(Arrays.toString(a2));

Java中split使用注意事项:

1.要被分解的String对象或文字,该对象不会被split方法修改。

2.字符串或正则表达式对象,它标识了分隔字符串时使用的是一个还是多个字符。如果忽略该选项,返回包含整个字符串的单一元素数组。

3.该值用来限制返回数组中的元素个数(也就是最多分割成几个数组元素,只有为正数时有影响)。

4.split 方法的结果是一个字符串数组,在 stingObj 中每个出现 separator 的位置都要进行分解。separator不作为任何数组元素的部分返回。

//随机生成数,并输出
import java.util.Arrays;
import java.util.Random;

public class t8 {
    public static void main(String[] args) {
        int a[]=new int[10];

        for(int i=0;i<a.length;i++){
            int b=new Random().nextInt(20);//随机生成20以内的10个数
            a[i]=b;
        }
        System.out.println(Arrays.toString(a));
    }
}

4、拷贝

拷贝若超过原数组的长度,会出现扩容现象。不够位置用0补齐。

 

import java.util.Arrays;

public class t7 {
    public static void main(String[] args) {
       int a[]=new int[]{1,8,9,7,5,6,54,56,8,6,53,34,45,56};
        System.out.println(a.length);//数组长度
        int[] copyof=Arrays.copyOf(a,14);
        System.out.println(Arrays.toString(copyof));//复制数组a到copyof
        int[] copyof1=Arrays.copyOf(a,18);//超过原数组的长度,会出现扩容现象。不够位置用0补齐。
        System.out.println(Arrays.toString(copyof1));
        int[] copyof2=Arrays.copyOf(a,6);//小于原数组的长度复制几位输出几位。
        System.out.println(Arrays.toString(copyof2));
    }}

5、冒泡排序

冒泡排序是一种比较简单的排序算法,它循环走过需要排序的元素,依次比较相邻的两个元素,如果顺序错误就交换,直至没有元素交换,完成排序。

若对n个人进行排序,我们需要n-1次比较,所以第k次比较需要进行n-k次比较。排序算法通过以数据对象的两两比较作为关键,所以可以得出,冒泡排序需要进行的

比较次数为:(n-1) + (n-2) + … + 1 = n*(n-1) / 2,因此冒泡排序的时间复杂度为O(n^2)

 

 

 //1.冒泡排序-s--两两比较,大的和小的换位置
   let dataList=[12,2,3,46,1,2,8];
   let hasSort=[];
  //第一遍循环 n-1 次  (n=dataList.length)
   for(let i=0;i<dataList.length;i++){
  //第二遍循环 n-i-1 次
         for(let j=0;j<i;j++){
           if(dataList[i]>dataList[j]){
            let _data = dataList[i]
            dataList[i] = dataList[j]
            dataList[j]=_data
           }
         }
         hasSort.push(dataList[i]);
   }
   console.log("hasSort:"+hasSort)
   //1.冒泡排序-end



public static void ArraySortTest() {

		int[] ages= {21,27,31,19,50,32,16,25};
		System.out.println(Arrays.toString(ages));
		//控制比较轮数
		for(int i=1;i<ages.length;i++) {
			//每轮比较多少
			for(int j=0;j<ages.length-i;j++) {
				if(ages[j]>ages[j+1]) {
					int tmp=0;
					tmp=ages[j];
					ages[j]=ages[j+1];
					ages[j+1]=tmp;					
				}}}
		System.out.println(Arrays.toString(ages));
	}

4、传递地址

数组可以作为方法的参数。

当调用方法的时候,向方法的小括号进行传参,传递进去的其实是数组的地址值。

 

 

 

 

 

 

6、值传递和引用传递的区别

1:按值传递是什么

指的是在方法调用时,传递的参数是按值的拷贝传递。

 

[java] view plain copy
public class TempTest {  
private void test1(int a){  
//做点事情  
}  
public static void main(String[] args) {  
TempTest t = new TempTest();  
int a = 3;  
t.test1(a);//这里传递的参数a就是按值传递  
}  
}  


//按值传递重要特点:传递的是值的拷贝,也就是说传递后就互不相关了。
[java] view plain copy
public class TempTest {  
private void test1(int a){  
a = 5;  
System.out.println("test1方法中的a="+a);  
}  
public static void main(String[] args) {  
TempTest t = new TempTest();  
int a = 3;  
t.test1(a);//传递后,test1方法对变量值的改变不影响这里的a  
System.out.println(”main方法中的a=”+a);  
}  
}  

2:按引用传递是什么

指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。

 

[java] view plain copy
public class TempTest {  
private void test1(A a){  
}  
public static void main(String[] args) {  
TempTest t = new TempTest();  
A a = new A();  
t.test1(a); //这里传递的参数a就是按引用传递  
}  
}  
class A{  
public int age = 0;  
}  

3:按引用传递的重要特点

传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。

 

[java] view plain copy
public class TempTest {  
private void test1(A a){  
a.age = 20;  
System.out.println("test1方法中的age="+a.age);  
}  
public static void main(String[] args) {  
TempTest t = new TempTest();  
A a = new A();  
a.age = 10;  
t.test1(a);  
System.out.println(”main方法中的age=”+a.age);  
}  
}  
class A{  
public int age = 0;  
}  
运行结果如下:
[java] view plain copy
test1方法中的age=20  
main方法中的age=20  
public class Poker {
    public static void main(String[] args) {
        //创建一个牌盒,也就是定义一个集合对象用ArrayList集合
        ArrayList<String> array=new ArrayList<>();

        //往牌盒里面装牌
        /* ♦2,♦3,♦4...♦K,♦A
        ♣2,...
        ♥2,...
        ♠2,...
        小王,大王
        */
        //定义花色数组
        String[] colors={"♦", "♣", "♥", "♠"};

        //定义点数数组
        String[] numbers={"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
    for(String color:colors){
        for(String number:numbers){
            array.add(color+number);
        }
    }
    array.add("大王");
    array.add("小王");

    //洗牌,也就是把牌打散,用collection的shuffle()方法实现

        Collections.shuffle(array);

        //发牌。也就是遍历集合,发给三个玩家发牌
        ArrayList<String> lqxArray=new ArrayList<String>();
        ArrayList<String> lyAArray=new ArrayList<String>();
        ArrayList<String> lqyArray=new ArrayList<String>();
        ArrayList<String> dpArray=new ArrayList<String>();

        for (int i = 0; i < array.size(); i++) {
            String poker=array.get(i);

            if(i>=array.size()-3){
                dpArray.add(poker);
            }else if(i%3==0){
                lqxArray.add(poker);
            } else if (i % 3 == 1) {
                lyAArray.add(poker);
            } else if (i % 3 == 2) {
                lqyArray.add(poker);
            }
        }
        //看牌,也就是三个玩家分别遍历自己的牌
        lookPoker("林青霞",lqxArray);
        lookPoker("柳岩",lyAArray);
        lookPoker("风清扬",lqyArray);
        lookPoker("底牌",dpArray);
    }
      //看牌方法
    public static void lookPoker (String name,ArrayList<String> array){
        System.out.println(name +"的牌是");
        for (String poker:array) {
            System.out.println(poker+" ");
        }
        System.out.println();
    }
}

七、面向对象:类

7.1基本概念

1、面向过程:当需要实现一个功能的时候,每一个具体的步骤都要亲力亲为,详细处理每一个细节。

2、面向对象:当需要实现一个功能的时候,不关心具体的步骤,而是找一个已经具有该功能的人,来帮我做事。

面向对象是基于面向过程而言。

 

三大特点:封装、继承和多态

使用面向对象:找到一个JDK 给我们提供好的Arrays类;其中有一个toString方法,直接就能把数组变成想要的格式的字符串

int[] arr={1,2,5,3,5}; System.out.println(arr.toString(arr));

 

 

 

对象三个特点:对象的状态、对象的行为和对象的标识

 

类的理解

类是对现实生活中一类具有共同属性和行为的事物的抽象

类是对象的数据类型,类是具有相同属性和行为的一组对象的集合

简单理解:类就是对现实事物的一种描述

类的组成

属性:指事物的特征,例如:手机事物(品牌,价格,尺寸)

行为:指事物能执行的操作,例如:手机事物(打电话,发短信)

类和对象的关系

类:类是对现实生活中一类具有共同属性和行为的事物的抽象

对象:是能够看得到摸的着的真实存在的实体

简单理解:类是对事物的一种描述,对象则为具体存在的事物

 

 

 

 

7.2 类的定义

类的组成是由属性和行为两部分组成

属性:在类中通过成员变量来体现(类中方法外的变量)

行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)

类的定义步骤:

①定义类

②编写类的成员变量

③编写类的成员方法

public class 类名 { // 成员变量 变量1的数据类型 变量1; 变量2的数据类型 变量2; … // 成员方法 方法1; 方法2; }

 

 

 

 

package cn.day02.demo01;
public class Student {
    //成员变量
    String name;//姓名
    int age;//性别

    //成员方法
    public void eat(){
        System.out.println("吃饭了");
    }
    public void sleep(){
        System.out.println("睡觉");
    }
    public void study(){
        System.out.println("学习");
    }
}

 

2、对象的创建及使用

通常情况下,一个类并不能直接使用,需要根据类创建一个对象,才能使用。

1.导包:也就是指出需要使用的类,在什么位置。

import 包名称.类名称;

import cn.itcast.day06.demo01.Student;

对于和当前类属于同一个包的情况,可以省略导包语句不写。

 

2.创建,格式:

类名称 对象名=new 类名称();

Student stu=new Student();

 

3.使用,分为两种情况;

使用成员变量:对象名.成员变量名

使用成员方法:对象名.成员方法名(参数);

也就是,想用谁,就用对象名点儿谁。

 

注意事项:如果成员变量没有进行赋值,那么将会有一个默认值,规则和数组一样。

 

public class Student {
    //成员变量
    String name;//姓名
    int age;//性别

    //成员方法
    public void eat(){
        System.out.println("吃饭了");
    }
    public void sleep(){
        System.out.println("睡觉");
    }
    public void study(){
        System.out.println("学习");
    }
}

public class Demo02Stuident {
    public static void main(String[] args) {
//        1.导包
//            我需要使用的Student类,和我自己Demo02Stuident位于同一个包下,所以省略导包语句不写.
//
//       2.创建,格式:
//        类名称 对象名=new 类名称();
//        根据Student类,创建了一个名为Stu的对象
        Student stu=new Student();

        //3.使用其中的变量,格式:
        //对象名.成员变量名
        System.out.println(stu.name);//null
        System.out.println(stu.age);//0

        System.out.println("============");
        //改变对象当中的成员变量数值内容
        //将右侧的字符串,赋值交给stu对象当中的name成员变量
        stu.name="张三";
        stu.age=14;
        System.out.println(stu.name);//张三
        System.out.println(stu.age);//14

        System.out.println("============");
        //4.使用对象的成员方法,格式:
        //对象名.成员方法();
        stu.eat();
        stu.sleep();
        stu.study();
    }}

练习手机:

类:

 

/*
定义一个类,用来模拟“手机”事务。
属性:品牌、价格、颜色
行为:打电话、发短信

对应到类当中:
成员变量(属性):
String brand;  //品牌
double price;//价格
String color;//颜色

成员方法(行为):
public void call(String who){} //打电话
public void sendMessage(){}//群发信息
*/
public class Phone {
    //成员变量
    String brand;  //品牌
    double price;//价格
    String color;//颜色

    //成员方法
    public void call(String who){
        System.out.println("给"+who+"打电话");
    } //打电话

    public void sendMessage(){
        System.out.println("群发信息");
    }//群发信息
}
函数:
public class Demo01PhoneOne {
    public static void main(String[] args) {
        //根据Phone类,创建一个名为one的对象
        //格式:类名称 对象名=new 类名称();
        Phone one=new Phone();

        //使用其中的变量,格式:
        //对象名.成员变量名
        System.out.println(one.brand);//null
        System.out.println(one.price);//0.0
        System.out.println(one.color);//null
        System.out.println("===========");

        //改变对象当中的成员变量数值内容
        //将右侧的字符串,赋值交给one对象当中的name成员变量
        one.brand="苹果";
        one.price=8888557.0;
        one.color="黑色";
        System.out.println(one.brand);//苹果
        System.out.println(one.price);//8888557.0
        System.out.println(one.color);//黑色
        System.out.println("===========");

        //使用对象的成员方法,格式:
        //对象名.成员方法();
        one.call("乔布斯");
        one.sendMessage();
        
        Phone two=new Phone();
System.out.println(two.brand);//null
System.out.println(two.price);//0.0
System.out.println(two.color);//null
System.out.println("===========");

two.brand="三星";
two.price=4057.0;
two.color="蓝色";
System.out.println(two.brand);//三星
System.out.println(two.price);//4057.0
System.out.println(two.color);//蓝色
 one.call("欧巴");
 one.sendMessage();
    }
}

 

 

堆与栈的区别很明显:

1.栈内存存储的是局部变量而堆内存存储的是实体;

2.栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;

3.栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。

堆:当需要一个对象时,只需用new写一行简单的代码,当执行这行代码时,会自动在堆里进行存储分配。

 

情况一.1:一个对象的内存图

 

 

 

 

 

 

 

情况一:两个引用指向同一个方法的内存图
Phone two=new Phone();
System.out.println(two.brand);//null
System.out.println(two.price);//0.0
System.out.println(two.color);//null
System.out.println("===========");

two.brand="三星";
two.price=4057.0;
two.color="蓝色";
System.out.println(two.brand);//三星
System.out.println(two.price);//4057.0
System.out.println(two.color);//蓝色
 one.call("欧巴");
 one.sendMessage();
    }
}

 

 

 

 

 

情况三
使用对象类型作为方法的参数
public class Demo01PhoneTwo {
    public static void main(String[] args) {
        Phone one=new Phone();
        one.brand="苹果";
        one.price=8888557.0;
        one.color="黑色";
        method(one);
    }

    private static void method(Phone param) {
        System.out.println(param.brand);
        System.out.println(param.price);
        System.out.println(param.color);
    }
}

 

 

 

 

 

 

情况四:使用对象类型作为方法的返回值
public class Demo01PhoneThree {
    public static void main(String[] args) {
        Phone two=getPhone();
        System.out.println(two.brand);//苹果
        System.out.println(two.price);//545.0
        System.out.println(two.color);//金玫瑰
    }

    private static Phone getPhone() {
        Phone one=new Phone();
        one.brand="苹果";
        one.price=545.0;
        one.color="金玫瑰";
        return one;
    }
}

 

 

 

 

 

八、成员变量和局部变量的区别:

类中位置不同:成员变量(类中方法外)局部变量(方法内部或方法声明上)

内存中位置不同:成员变量(堆内存)局部变量(栈内存)

生命周期不同:成员变量(随着对象的存在而存在,随着对象的消失而消失)局部变量(随着方法的调用而 存在,醉着方法的调用完毕而消失)

初始化值不同:成员变量(有默认初始化值)局部变量(没有默认初始化值,必须先定义,赋值才能使用)

1.定义的位置不一样【重点】

局部变量:在方法的内部

成员变量:在方法的外部,直接写在类当中

 

public class Student {
    private String name;//成员变量
    private int age;//成员变量
    public void method1(){
        int num=20;//局部变量
    }
  }

public class t1 {
    //成员变量:类的成员  static静态资源
    static int a=10;//10
    static int b;//0
    static float b1;//0.0
    static char b2;//空
    static String c;//null

    public static void main(String[] args) {
        method();
    }

    private static void method() {
        int a=20;//局部变量
        //就近原则
        System.out.println(a);//20
        System.out.println(b);//0
        System.out.println(b1);//0.0
        System.out.println(b2);//空
        System.out.println(c);//null
    }
}

2.作用范围不一样【重点】

局部变量:只有方法当中才可以使用,出了方法就不能再用

成员变量:整个类全都可以通用

 

3.默认值不一样【重点】

局部变量:没有默认值,如果要想使用,必须手动进行赋值

成员变量:如果没有赋值,会有默认值,规则和数组一样

 

4.内存的位置不一样(了解)

局部变量:位于栈内存

成员变量:位于堆内存

 

5.生命周期不一样(了解)

局部变量:随着方法进栈而诞生,随着方法出栈而消失(时间短)

成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失(时间长)

public class t1 {
    String name;//成员变量
    public void methodA(){
        int num=20;//局部变量
        System.out.println(num);
        System.out.println(name);
    }
    public void methodB(int param){//方法的参数就是局部变量
        //参数在方法调用的时候,必然会被赋值
        System.out.println(param);

        int age;//局部变量
 //       System.out.println(age);//没赋值不能用

        //     System.out.println(num);//错误写法
        System.out.println(name);
    }
}

九、面向对象三大特征

封装、继承、多态

 

9.1封装

private是一个修饰符,可以用来修饰成员(成员变量,成员方法)

被private修饰的成员,只能在本类进行访问,针对private修饰的成员变量,如果需要被其他类使用,提供相 应的操作

提供“get变量名()”方法,用于获取成员变量的值,方法用public修饰

提供“set变量名(参数)”方法,用于设置成员变量的值,方法用public修饰

 

对于封装而言,一个对象它所封装的是自己的属性和方法,所以它是不需要依赖其他对象就可以完成自己的操作。使用封装有三大好处:

1、良好的封装能够减少耦合。

2、类内部的结构可以自由修改。

3、可以对成员进行更精确的控制。

4、隐藏信息,实现细节。

 

在Java中的体现

1.方法就是一种封装

2.关键字private也是一种封装

封装就是将一些细节信息隐藏起来,对外界不可见。

作用:

1)提高安全性

2)提高重用性

练习题1:

 

public class Demo01 {
    public static void main(String[] args) {
        int[] array={5,15,25,20,100};

        int max=getMax(array);
        System.out.println("最大值"+max);
    }

    //给我一个数组,我还给你一个最大值
    private static int getMax(int[] array) {
        int max=array[0];
        for(int i=1;i<array.length;i++){
            if(array[i]>max){
                max=array[i];
            } }
        return max;
    }}
练习题2:
/*
问题描述:定义Person的年龄时,无法阻止不合理的数值被设置进来。
解决方案:用private关键字将需要保护的成员变量进行修饰。

一旦使用了private进行修饰,那么本类当中仍然可以随意访问。
但是!超出了本类范围之外就不能在直接访问了。

间接访问private成员变量,就是定义一对儿Getter/Setter方法
格式:
必须叫setXxx或者是getXxx命名规则。
对于Getter来说,不能有参数,返回值类型和成员变量对应;
对于Setter来说,不能有返回值,参数类型和成员变量对应。
 */
public class Person {
    String name; //姓名
    private int age;// 年龄
    public void show(){
        System.out.println("我叫:"+name+",年龄:"+age);
    }

    //成员方法,专门用于向age设置数据
    public void setAge(int num){//set方法设置值,不需要返回值,需要参数
        if (num<100&&num>=9){
            age=num;//如果是合理情况
        }else{
            System.out.println("数据不合理!");
        } }
    //这个成员方法,专门私语获取age的数据
    public int getAge(){//get方法取值,不需要参数,需要返回值
        return age;
    }
}


public class Demo03Person {
    public static void main(String[] args) {
        Person person=new Person();
        person.show();

        person.name="赵丽颖";
        //person.age=-20;//直接访问private内容,错误写法!
        person.show();

        person.setAge(20);
        System.out.println();
    }
}


private定义学生类
/*
对于基本类型当中的boolean值,Getter方法一定要写成isXxx的形式,而setXxx规则不变。

 */
public class Student {
    private String name;//姓名
    private int age;//年龄
    private boolean male;//是不是爷们

    //是不是爷们boolean
    public void setMale(boolean b){
        male=b;
    }
    public boolean isMale(){
        return male;
    }

    //姓名
    public void setName(String str){
        name=str;
    }
    public String getName(){
        return name;
    }

    //年龄
    public void setAge(int num){
        age=num;
    }
    public int getAge(){
        return age;
    }}


public class Demo01Student {
    public static void main(String[] args) {
        Student stu=new Student();

        stu.setName("鹿晗");
        stu.setAge(22);
        stu.setMale(true);

        System.out.println("姓名:"+stu.getName());
        System.out.println("年龄:"+stu.getAge());
        System.out.println("是不是爷们儿:"+stu.isMale());
    }
}

9.2 this关键字

 

this修饰的变量用于指代成员变量,其主要作用是(区分局部变量和成员变量的重名问题)

方法的形参如果与成员变量同名,不带this修饰的变量指的是形参,而不是成员变量。

方法的形参没有与成员变量同名,不带this修饰的变量指的是成员变量。

 

当方法的局部变量和类的成员变量重名的时候,根据”就近原则“,优先使用局部变量。

如果需要访问本类当中的成员变量,需要使用格式

this.成员变量

"通过谁调用的方法,谁就是this."

/*
当方法的局部变量和类的成员变量重名的时候,根据”就近原则“,优先使用局部变量。
如果需要访问本类当中的成员变量,需要使用格式
this.成员变量
"通过谁调用的方法,谁就是this."
 */
public class Person {
    //成员变量
    String name;//我自己的名字

    //参数name是对方的名字
    //成员变量name是自己的名字
    //局部变量
    public void sayHello(String name){
        System.out.println(name+",你好!我是:"+this.name);
        System.out.println(this);
    }
}

public class demo01Person {
    public static void main(String[] args) {
        Person person=new Person();
        //设置我自己的名字
        person.name="王健林";
        person.sayHello("王世聪");

        System.out.println();//地址值
    }
}

 

 

this内存原理【理解】

this代表当前调用方法的引用,哪个对象调用的方法,this就代表哪一个对象

 

封装思想【理解】

1. 封装概述 是面向对象三大特征之一(封装,继承,多态) 是面向对象编程语言对客观世界的模拟,客观世界 里成员变量都是隐藏在对象内部的,外界是无法直接操作的

2. 封装原则 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏 信息的操作和访问 成员变量private,提供对应的getXxx()/setXxx()方法

3. 封装好处 通过方法来控制成员变量的操作,提高了代码的安全性 把代码用方法进行封装,提高了代码的复用 性

 

9.3 构造方法和定义一个标准类

构造方法是一种特殊的方法

作用:创建对象 Student stu = new Student();

格式:

public class 类名{

修饰符 类名( 参数 ) { }

}

功能:主要是完成对象数据的初始化

 

构造方法的创建:

如果没有定义构造方法,系统将给出一个默认的无参数构造方法 如果定义了构造方法,系统将不再提供默认的构造 方法。

构造方法的重载 :

如果自定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法 。

推荐的使用方式 :

无论是否使用,都手工书写无参数构造方法。

重要功能!

可以使用带参构造,为成员变量进行初始化

 

构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法。

格式:

public 类名称(参数类型 参数名称){

方法体

}

 

注意事项:

1.构造方法的名称必须和所在的类名称完全一样,就连大小写也要一样。

2.构造方法不要写返回值类型,连void都不写。

3.构造方法不能写return一个具体的返回值。

4.如果没有编写任何构造方法,那么编译器将会默认赠送一个构造方法,没有参数、方法体什么事情都不做。

public Student(){}

5.一旦编写至少一个构造方法,那么编译器将不再赠送。

6.构造方法也是可以进行重载的。

重载:方法名称相同,参数列表不同。

/*
构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法
格式:
public 类名称(参数类型 参数名称){
方法体
}

注意事项:
1.构造方法的名称必须和所在的类名称完全一样,就连大小写也要一样。
2.构造方法不要写返回值类型,连void都不写。
3.构造方法不能写return一个具体的返回值。
4.如果没有编写任何构造方法,那么编译器将会默认赠送一个构造方法,没有参数、方法体什么事情都不做。
public Student(){}
5.一旦编写至少一个构造方法,那么编译器将不再赠送。
6.构造方法也是可以进行重载的。
重载:方法名称相同,参数列表不同。
 */
public class Student {
    //成员变量
    private String name;
    private int age;

    //无参数的构造方法
    public Student(){
        System.out.println("无参构造方法执行了!");
    }

    //全参数的构造方法
    public Student(String name,int age){
        System.out.println("全参构造方法执行了!");
        this.name=name;
        this.age=age;
    }
    //Getter  Setter
    public  void setName(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
    public void setAge(int age){
        this.age=age;
    }

    public int getAge() {
        return age;
    }
}

public class Demo02Student {
    public static void main(String[] args) {

        Student stu1=new Student();//无参构造
        System.out.println("============");

        Student stu2=new Student("赵丽颖",20);//全参构造
        System.out.println("姓名:"+stu2.getName()+", 年龄"+stu2.getAge());

        //如果需要改变对象当中的成员变量数据内容,仍然还需要使用setXxx方法
        stu2.setAge(21);//改变年龄
        System.out.println("姓名:"+stu2.getName()+", 年龄"+stu2.getAge());
    }
}


练习二:
/*
一个标准的类通常要拥有下面四个组成部分:
1.所有的成员变量都要使用private关键字修饰。
2.为每一个成员变量编写一对儿Getter/Setter方法
3.编写一个无参数的构造方法
4.编写一个全参数的构造方法

这样标准的类也叫做JavaBean
 */
public class Student {
    private String name;
    private int age;

    //无参构造方法
    public Student() {
    }

    //全参构造方法
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name=name;
    }
    public int getAge(){
        return age;
    }
    public void setAge(int age){
        this.age=age;
    }
}


public class Demo01Student {
    public static void main(String[] args) {
        Student stu1=new Student();

        stu1.setAge(20);
        stu1.setName("迪丽热巴");
        System.out.println("姓名:"+stu1.getName()+",年龄"+stu1.getAge());
        System.out.println("=============");

        Student stu2=new Student("张思",23);
        System.out.println("姓名:"+stu2.getName()+",年龄"+stu2.getAge());
        stu2.setAge(45);
        System.out.println("姓名:"+stu2.getName()+",年龄"+stu2.getAge());
    }
}

 

9.4 API标准概述和使用步骤

什么是API API (Application Programming Interface) :应用程序编程接口。

java中的API 指的就是 JDK 中提供的各种功能的 Java类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何 实现的,只需要学习这些类如何使用即可,我们可以通过帮助文档来学习这些API如何使用。

 

 

9.5 Scanner

可以实现键盘输入数据,到程序当中

1、Scanner概述及API的使用

 

Scanner类的功能:可以实现键盘输入数据,到程序当中。
引用类型的一般使用步骤:

1.导包
import 包路径.类名称;
如果需要使用的目标类,和当前类位于同一个包下,则可以省略导包语句不写。
如果java.long包下的内容不需要导包,其他的包都需要import语句。

2.创建
类名称 对象名=new 类名称();

3.使用
对象名.成员方法名();
2、Scanner使用步骤
/*
获取键盘输入的一个int数字:int num=sc.nextInt();
获取键盘输入的一个字符串:String str=sc.next();
 */
//1.导包
import java.util.Scanner;
public class Demo01Scanner {
    public static void main(String[] args) {
         // 2.创建:备注:System.in代表从键盘进行输入
        // 类名称 对象名=new 类名称();
        Scanner sc=new Scanner(System.in);

        //3.获取键盘输入的一个int数字:
        int num=sc.nextInt();
        System.out.println("输入的int数字:"+num);

        //4.获取键盘输入的一个字符串
        String str=sc.next();
        System.out.println("输入的字符串是:"+str);
    }
}


3、Scanner练习
习题一:
/*
题目:键盘输入两个数,并求出和值。

思路:
1.既然需要键盘输入,那么就用Scanner
2.Scanner的三个步骤:导包、创建、使用
3.需要的是两个数字,所以要调用两次nextInt方法
4.得到两个数字,就需要加在一起
5.将结果打印输出
 */
import java.util.Scanner;

public class Demo03Scanner {
    public static void main(String[] args) {

        System.out.println("输入第一个数:");
        //Scanner sc=new Scanner(System.in);
        //int x=sc.nextInt();
        int x=new Scanner(System.in).nextInt();
        
        System.out.println("输入第二个数:");
        //int y=sc.nextInt();
       int y=new Scanner(System.in).nextInt();

        int sum=x+y;
        System.out.println("求和:"+sum);
    }
}

习题二:
/*
题目:键盘输入三个int数字,然后求出其中的最大值。

思路:
1.既然是键盘输入,肯定需要用到Scanner
2.Scanner三个步骤:导包、创建、使用nextInt()方法
3.既然是三个数字,那么调用三次nextInt()方法,得到三个int变量
4.无法同时判断三个数字谁最大,应该转换成为两个步骤
4.1首先判断前两个当中谁最大,拿到前两个的最大值
4.2拿着当前两个中的最大值,再和第三个数字比较,得到三个数字当中的人最大值
5.打印最终结果

 */
public class Demo02Scannersum {
    public static void main(String[] args) {
        System.out.println("输入第一个数字");
        int x=new Scanner(System.in).nextInt();
        System.out.println("输入第二个数字");
        int y=new Scanner(System.in).nextInt();
        System.out.println("输入第三个数字");
        int z=new Scanner(System.in).nextInt();
        int t=x>y?x:y;
        int max=t>z?t:z;
        System.out.println("最大值:"+max);
    }
}

4、匿名对象的说明
public class Person {
    String name;
    public void showName() {
        System.out.println("我叫:" + name);
    }}

/*
创建对象的标准格式:
类名称 对象名=new 类名称();

匿名对象就是只有右边的对象,没有左边的名字和赋值运算符。
new 类名称();

注意事项:匿名对象只能使用唯一的一次下次再用不得不再创建一个新对象。
使用建议:如果确定有一个对象只需要使用唯一的一次,就可以用匿名对象。
 */
public class Demo01Anonymous {
    public static void main(String[] args) {
        //类名称 对象名=new 类名称();
        Person one=new Person();
        one.name="高圆圆";
        System.out.println(one.name);
        one.showName();//我叫:高圆圆

        //匿名对象
        new Person().name="赵又廷";
        new Person().showName();//?我叫null
    }
}


5、匿名对象作为方法的参数和返回值
public class Demo02Anonymous {
    public static void main(String[] args) {
        System.out.println("请输入数字:");
        //普通使用方式
        //int sc=new Scanner(System.in).nextInt();

        //匿名对象方式
        //int num=new Scanner(System.in).nextInt();
        //System.out.println("输入的是:"+num);

        //使用一般写法传入参数
        //Scanner sc=new Scanner(System.in);
        //methodParam(sc);

        //使用匿名对象来进行传参
        //methodParam(new Scanner(System.in));

        Scanner sc=methodReturn();
        int num=sc.nextInt();
        System.out.println("输入的是:"+num);

    }
    public static void methodParam(Scanner sc){

       int num=sc.nextInt();
        System.out.println("输入的数字是:"+num);
    }
    public static Scanner methodReturn(){
        //Scanner sc=new Scanner(System.in);
       // return sc;
        return new Scanner(System.in);
    }
}

9.6 Random

1、Random的概述和基本使用和生成指定范围的随机数

Random类用来生成随机数字。使用起来也是三个步骤:

1.导包

import java.util.Random;

 

2.创建

Random r=new Random();//小括号当中留空即可

 

3.使用

获取一个随机的int数字(范围是int所有范围,有正负两种),int num=r.nextInt();

获取一个随机的int数字(参数代表了范围,左闭右开区间),int num=r.nextInt(10);

实际上代表的含义是:[0,10) 0-9

 

public class Demo01Random {
    public static void main(String[] args) {
        Random r=new Random();
        int num=r.nextInt();//范围是int所有范围,有正负两种

        int num1=new Random().nextInt(10);//范围在10以内
        System.out.println("生成随机数:"+num);
        System.out.println("生成随机数:"+num1);

        System.out.println("================");
        Random r1=new Random();
        int index=0;
        for(int i=0;i<20;i++){
            int n=r1.nextInt(5);//范围实际上是:0-4
            System.out.print("   "+n);
        }

    }
}

练习一:生成1-n的随机数
/*
题目要求:
根据int变量n的值,来获取随机数字,范围是[1,n],可以取到1也可以取到n.

思路:
1.定义一个int变量n,随意赋值。
2.要使用Random:三个步骤:导包,创建,使用
3.如果写10,那么就是0~9,然而想要的是1~10,可以发现:整体+1即可
4.打印随机数字

 */
public class Demo02Random {
    public static void main(String[] args) {
        int n=5;
        Random r=new Random();
        for(int i=0;i<100;i++){
        int result=r.nextInt(n)+1; //本来范围是[0,n],整体+1之后变成[1,n+1],也就是[1,n]
        System.out.println(result);
    }
    }
}

练习二:
/*
题目:
用代码模拟猜数字的小游戏。

思路:
1.首先需要产生一个随机数,并且一旦产生不在变化。用Random的nextInt方法
2.需要键盘输入,所以用到了Scanner
3.获取键盘输入的数字,用Scanner当中的nextInt方法
4.已经得到两个数字,判断(if)一下
   如果太大了,提示太大,并重试;
   如果太小了,提示太小,并重试;
   如果猜中了,游戏结束
5.重试就是再来一次,循环次数不确定用while(true)
 */
import java.util.Random;
import java.util.Scanner;

public class Demo03Random {
    public static void main(String[] args) {
        int r = new Random().nextInt(100) + 1;//[1,100]
        while (true) {
            System.out.println("输入数字:");
            int x = new Scanner(System.in).nextInt();
            if (x > r) {
                System.out.println("猜大了");
            } else if(x<r){
                System.out.println("猜小了");
            }else{
                System.out.println("恭喜猜对了");
                break;
            }
            }
        System.out.println("结束");
        }
    }

快捷键添加构造方法和get、set方法:将光标放到成员变量,按下快捷键Alt+Insert

 

 

 

9.7 ArrayList

什么是集合:

提供一种存储空间可变的存储模型,存储的数据容量可以发生改变。

ArrayList集合的特点

底层是数组实现的,长度可以变化 。

泛型的使用

用于约束集合中存储元素的数据类型。

 

1、ArrayList集合概述和基本使用

数组的长度不可以发生改变。

但是ArrayList集合的长度是可以随意变化的。

 

对于ArrayList来说,有一个尖括号<E>代表泛型。

泛型:也就是装在集合当中的所有元素,全都是统一的什么类型。

注意:泛型只能是引用类型,不能是基本类型。

 

注意事项:

对于ArrayList集合来说,直接打印得到的不是地址值,而是内容。

如果内容是空,得到的是空的中括号:[]

public class arraylist01 {
    public static void main(String[] args) {
        //创建了一个ArrayList集合,集合的名称是list,里面装的全都是String字符串类型的数据
        //备注:从JDK1.7+开始,右边的尖括号内部可以不写内容,但是<>本身还是要写的。
        ArrayList<String> list=new ArrayList<>();
        System.out.println(list);//[]

        //向集合当中添加一些数据,需要用到add方法。
        list.add("赵丽颖");
        System.out.println(list);//[赵丽颖]

        list.add("赵四");
        list.add("张翰");
        list.add("刘坤");
        System.out.println(list);//[赵丽颖, 赵四, 张翰, 刘坤]
        //指定位置插入
        list.add(2,"张宏里");
        System.out.println(list);//[赵丽颖, 赵四, 张宏里, 张翰, 刘坤]
     }
}

2、ArrayList集合的常用方法和遍历

 

1.ArrayList常用方法有

public boolean add(E e):向集合当中添加元素,参数的类型和泛型一致。

public E get (int index):从集合当中获取元素,参数是索引编号”下标从0开始“,返回值就是对应位置的元素。

public E remove(int index):从集合当中删除元素,参数是索引编号,返回值就是被删除掉的元素。

public int size():获取集合的尺寸长度,返回值是集合中包含的元素个数。

 

public class arraylist02 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        System.out.println(list);//[]

        //1.向集合中添加元素:add
        boolean success= list.add("柳岩");
        System.out.println(list);//[柳岩]
        System.out.println("添加的动作成功:"+success);//true

        list.add("张氏");
        list.add("胡歌");
        list.add("张绍云");
        System.out.println(list);//[柳岩, 张氏, 胡歌, 张绍云]

        //2.从集合中获取元素:get。索引值从0开始
        String name=list.get(2);
        System.out.println("第2号索引位置:"+name);//胡歌

        //3.从集合中删除元素:remove。索引值从0开始
        String whoRemove=list.remove(3);
        System.out.println("被删除的人是:"+whoRemove);//张绍云
        System.out.println(list);//[柳岩, 张氏, 胡歌]

        //4.获取集合的长度尺寸,也就是其中元素的个数
        int size= list.size();
        System.out.println("集合的长度是:"+size);//3

    }
}
   
 2.遍历:遍历{快捷键:list.fori}
public class arraylist03 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        list.add("赵丽颖");
        list.add("胡歌");
        list.add("张三");
        list.add("刘涛");
        list.add("刘四");

        //遍历{快捷键:list.fori}
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
               //遍历集合通用格式
               // String s=list.get(i);
               // System.out.println(s);
        }
    }
}


3、ArrayList集合存储基本数据类型
/*
如果希望向集合ArrayList当中存储基本类型数据,必须使用基本类型对应的”包装类“。

基本类型       包装类(引用类型,包装类都位于java.long包下)
int           Integer
char          Character
byte          Byte
short         Short
long          Long
float         Float
double        Double
boolean       Boolean
从JDK1.5+开始,支持自动装箱、自动拆箱

自动装箱:基本类型---->包装类型
自动拆箱:包装类型---->基本类型
 */
public class arraylist04 {
    public static void main(String[] args) {
        ArrayList<String> listA=new ArrayList<>();
        //错误写法!泛型只能是引用类型,不能是基本类型
        //ArrayList<int> listB=new ArrayList<>();

        ArrayList<Integer> listC=new ArrayList<>();
        //向集合中添加元素:add
        listC.add(100);
        listC.add(200);
        System.out.println(listC);//[100, 200]

        //从集合中获取元素:get。索引值从0开始
        int num=listC.get(1);
        System.out.println("第一个元素是:"+num);//200
    }
}

4、练习
练习一:存储随机数
/*
题目:
生成6个1~33之间的随机数,添加到集合,并遍历集合

思路:
1.需要存储6个数字,创建一个集合,<Integer>
2.产生随机数,需要用到Random
3.用循环6次,来产生6个随机数字:for循环
4.循环内调用r.nextInt(int n),参数是33,0~32,整体+1才是1~33
5.把数字添加集合中:add
6.遍历集合:for、size、get
 */
public class arraylist05 {
    public static void main(String[] args) {
        ArrayList<Integer> list=new ArrayList<>();
        //获得随机数
        for (int i = 0; i < 6; i++) {
            int r=new Random().nextInt(33)+1;
            list.add(r);
        }
        //遍历集合
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
}

练习二:存储自定义对象
/*
题目:
自定义4个学生对象,添加到集合,并遍历

思路:
1.自定义Student学生类,四个部分。
2.创建一个集合,用来存储学生对象。泛型:<Student>
3.将4个学生对象添加到集合中:add
4.遍历集合:for、size、get
 */
public class arraylist07 {
    public static void main(String[] args) {

        ArrayList<Student> list=new ArrayList<>();
        Student one=new Student("张翰",32);
        Student two=new Student("郭靖",66);
        Student three=new Student("张国立",72);
        Student four=new Student("胡歌",32);

        list.add(one);
        list.add(two);
        list.add(three);
        list.add(four);

        //遍历集合
        for (int i = 0; i < list.size(); i++) {
            //System.out.println(list.get(i));
            Student stu=list.get(i);
            System.out.println("姓名:"+stu.getName()+",龄:"+stu.getAge());
        }
    }
}


public class Student {
    private String name;
    private int age;
//无参构造
    public Student() {
    }
//全参构造
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }
}

练习三:按指定格式遍历集合字符串
/*
题目:
定义以指定格式打印集合的方法(Arraylist类型作为参数),使用{}括起来集合,使用@分隔每个元素。
格式参照{元素@元素@元素}。

System.out.println(list);      [10,20,30]
printArraylist(list);          {10,20,30}
 */
public class arraylist06 {
    public static void main(String[] args) {

        ArrayList<String> list=new ArrayList<>();
        list.add("张三丰");
        list.add("张无忌");
        list.add("张翠山");
        list.add("张晓明");
        System.out.println(list);

        printArraylist(list);
    }
    /*
    定义方法的三要素:
    返回值类型:只是进行打印而已,没有运算,没有结果,所以用viod
    方法名称:printArraylist
    参数列表:ArrayList
     */
    public static void printArraylist(ArrayList<String> list){

        System.out.print("{");
        for(int i=0;i<list.size();i++){
            String name =list.get(i);
            if(i== list.size()-1){
                System.out.println(name+"}");
            }else {
                System.out.print(name + "@");
 }   }    }}

练习四:筛选集合中的随机数

/*
题目:
用一个大集合存入20个随机数字,然后筛选其中的偶数元素,放到小集合当中
要求使用自定义的方法来实现筛选。

分析:
1.需要创建一个大集合,用来存储int数字:<Integer>
2.随机数就用Random nextInt
3.循环20次,把随机数字放入大集合:forx循环、add方法
4.定义一个方法,用来筛选符合要求的元素,得到小集合
筛选:根据大集合,筛选符合要求的元素,得到小集合。
三要素:
返回值类型:ArrayList小集合(里面元素个数不确定)
方法名称:getSmallList
参数列表:ArrayList大集合(装20个随机数字)
5.判断(if)是偶数:num%2==0
6.如果是偶数,就放到小集合当中。否则不放
 */
public class return01 {
    public static void main(String[] args) {
        //创建了一个ArrayList集合,集合的名称是biglist,里面装的全都是int型数据
        ArrayList<Integer> biglist=new ArrayList<>();
        Random r=new Random();
        for (int i = 0; i < 20; i++) {
            int num=r.nextInt(100)+1;//1~100
            biglist.add(num);
        }
        ArrayList<Integer> smallList=getSmallList(biglist);
        System.out.println("偶数总共有:"+smallList.size());
        for(int i=0;i<smallList.size();i++)
        {
            System.out.println(smallList.get(i));
        }
    }
    //这个方法,接受大集合参数,返回小集合结果
    public static ArrayList<Integer> getSmallList(ArrayList<Integer> biglist){
        //创建一个小集合,用来装偶数结果
        ArrayList<Integer> smallList=new ArrayList<>();
        for(int i=0;i<biglist.size();i++){
            int num=biglist.get(i);
            if(num%2==0){
                smallList.add(num);
            }
        }
        return smallList;
    }
}

十、字符串String

 

1、charAt(int index):返回指定索引处的 char 值。

2、indexOf(String ch):返回指定字符在此字符串中第一次出现处的索引。

3、isEmpty():当且仅当 length() 为 0 时返回 true。

4、lastIndexOf(String ch):返回指定字符在此字符串中最后一次出现处的索引。

5、length():返回此字符串的长度。

6、replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。

7、split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串。

8、startsWith(String prefix):测试此字符串是否以指定的前缀开始。

9、toLowerCase():使用默认语言环境的规则将此 String 中的所有字符都转换为小写。

10、String toUpperCase():使用默认语言环境的规则将此 String 中的所有字符都转换为大写。

11、contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true。

 

10.1 字符串构造方法和直接创建

构造方法:

public String() 创建一个空白字符串对象,不含有任何内容

public String(char[] chs) 根据字符数组的内容,来创建字符串对象

public String(byte[] bys) 根据字节数组的内容,来创建字符串对象

String s = “abc”; 直接赋值的方式创建字符串对象,内容就是abc

 

public class t1 {
    public static void main(String[] args) {
        //public String():创建一个空白字符串对象,不含有任何内容
        String s1=new String();
        System.out.println("s1:"+s1);//

        //public String(char[] chs):根据字符数组的内容,来创建字符串对象
        char[] chs={'a','b','c'};
        String s2=new String(chs);
        System.out.println("s2:"+s2);//abc

        //public String(byte[] bys):根据字节数组的内容,来创建字符串对象
        byte[] bys={97,98,99};
        String s3=new String(bys);
        System.out.println("s3:"+s3);//abc

        //String s = “abc”; 直接赋值的方式创建字符串对象,内容就是abc
        String s4="abc";
        System.out.println("s4:"+s4);//abc
    }
}

 

10.2 字符串常量池

通过构造方法创建 :String s3=new String(类型);

通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同直接赋值方式创建 : String s4="abc";

以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一 个 String 对象,并在字符串池中维护

10.3 字符串方法

 

public StringBuilder append (任意类型) 添加数据,并返回对象本身。

public StringBuilder reverse() 返回相反的字符序列。

public int length() 返回长度,实际存储值。

public String toString() 通过toString()就可以实现把StringBuilder转换为String。

 

1、比较相关法

= =号的作用:

比较基本数据类型:比较的是具体的值

比较引用数据类型:比较的是对象地址值

 

方法介绍:比较两个字符串内容是否相同、区分大小写

public boolean equals(String s) 比较两个字符串内容是否相同、区分大小写

public boolean equals(Object anObject):将此字符串与指定对象进行比较。由于我们比较的是字符串对象,所以参数直接传递一个字符串

 

public class t2 {
    public static void main(String[] args) {
        //构造方法的方式得到对象
        char[] chs={'a','b','c'};
        String s1=new String(chs);
        String s2=new String(chs);
        System.out.println(s1);//abc
        System.out.println(s2);//abc
        System.out.println("===========");

        //直接赋值的方式得到对象
        String s3="abc";
        String s4="abc";

        //比较字符串对象【地址】是否相同
        System.out.println(s1==s2);//false
        System.out.println(s1==s3);//false
        System.out.println(s3==s4);//true
        System.out.println("===========");

        //比较字符串【内容】是否相同
        System.out.println(s1.equals(s2));//true
        System.out.println(s1.equals(s3));//true
        System.out.println(s1.equals(s4));//true
    }
}

 

练习
public class t3 {
    public static void main(String[] args) {
        //已知用户名和密码,定义两个字符串表示即可
        String username = "heima";
         String password = "1234";

        //用循环实现多次机会,这里的次数明确,
        // 采用for循环实现,并在登录成功的时候,使用break结束循环
        for (int i = 0; i < 3; i++) {
            //键盘录入要登录的用户名和密码,用 Scanner 实现
            Scanner sc=new Scanner(System.in);

            System.out.println("输入用户名:");
            String name=sc.nextLine();

            System.out.println("输入密码:");
            String pwd=sc.nextLine();

            //拿键盘录入的用户名、密码和已知的用户名、密码进行比较,给出相应的提示。
            // 字符串的内容比较,用equals() 方法实现
          if (name.equals(username)&&pwd.equals(password)){
              System.out.println("登陆成功");
              break;
          }else{
              if(2-i==0){
                  System.out.println("密码被锁定,请联系管理员解锁");
              }else{
                  System.out.println("登陆失败,还有"+(2-i)+"次机会");
              }          }        }    }}

charAt(int index)方法是一个能够用来检索特定索引下的字符的String实例的方法.

charAt()方法返回指定索引位置的char值。索引范围为0~length()-1.

 

执行自动类型转换需要两个条件:

1、两种类型是兼容的,比如所有的数字类型都是兼容的,而数字类型和布尔类型是不兼容的

2、目的类型的范围比源类型的大。如:从int类型向float类型转换可以自动实现,反之则需要进行强制类型转换。

 

所谓强制类型转换实际上只是一种显示类型的转换

2、获取相关法

charAt(int index)方法是一个能够用来检索特定索引下的字符的String实例的方法.

charAt()方法返回指定索引位置的char值。索引范围为0~length()-1.

/*
思路:
1:定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
2:定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回。
返回值类型 String,参数列表 int[] arr
3:在方法中遍历数组,按照要求进行拼接
4:调用方法,用一个变量接收结果
5:输出结果
*/

public class t6 {
    public static void main(String[] args) {
        //定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
        int[] a={1,2,3,4};
        //调用方法,用一个变量接收结果
        String s=array(a);
        //输出结果
        System.out.println("s:"+s);
    }
    //定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回
/*
两个明确:
返回值类型:String
参数:int[] arr
*/
    private static String array(int[] a) {
        //在方法中遍历数组,按照要求进行拼接
        String s=" ";       
        s=s+"[";
        for (int i = 0; i < a.length; i++) {
            if (i==a.length-1){
                s=s+a[i];
            } else{
                s+=a[i];
                s+=",";
            }
        }
        s=s+"]";
        return s;
    }
}

3、截取相关法
subString(int index):截取从参数位置一直到字符串末尾,返回新字符串。
/*
字符串的截取方法:
public String subString(int index):截取从参数位置一直到字符串末尾,返回新字符串。
public String subString(int index,int end):截取从begin开始,一直到end结束,中间的字符串。
备注:
[index,end),包含左边,不包含右边。
 */
public class t3 {
    public static void main(String[] args) {
        String str1="HelloWord";

        String str2=str1.substring(5);
        System.out.println(str1);//HelloWord
        System.out.println(str2);//Word
        System.out.println("===========");

        //下面这种写法,字符串的内容仍然是没有改变的
        //下面有两个字符串:"hello"    "java"
        //str中保存的是地址值
        //本来地址值是hello中的地址0x66
        //后来地址值变成了0x999
        String strA= "hello" ;
        System.out.println(strA);//hello
         strA="java";
        System.out.println(strA);//java
    }
}


4、转换相关法
/*
String 当中与转换相关的常用方法
public char[] toCharArray():将当前字符串拆分成为字符数组作为返回值。
public byte[] getBytes():获得当前字符串底层的字节数组。
public String[] replace(CharSequence oldString,CharSequence newString);
将所有出现的老字符串替换成新的字符串,返回替换之后的结果新字符串。
备注:CharSequence意思就是说可以接受字符串类型
 */
public class t4 {
    public static void main(String[] args) {
        //转换成为字符数组
        char[] chars = "Hello".toCharArray();
        System.out.println(chars[0]);//H
        System.out.println(chars.length);//5
        System.out.println("=============");

        //转换成为字节数组
        byte[] bytes = "abc".getBytes();
        for (int i = 0; i < bytes.length; i++) {
            System.out.println(bytes[i]);
        }
        System.out.println("==========");

        //字符串的内容转换
        String str1 = "How do you do";
        String str2 = str1.replace("o", "*");
        System.out.println(str1);//How do you do
        System.out.println(str2);//H*w d* y*u d*

        String lang1 = "会不会玩,会不会玩,你大爷的!你大爷的!";
        String lang2=lang1.replace("你大爷的","****");
        System.out.println(lang2);//会不会玩,会不会玩,****!****!
        //System.out.println(lang1);
    }
}


/*
思路:
1:键盘录入一个字符串,用 Scanner 实现
2:定义一个方法,实现字符串反转。返回值类型 String,参数 String s
3:在方法中把字符串倒着遍历,然后把每一个得到的字符拼接成一个字符串并返回
4:调用方法,用一个变量接收结果
5:输出结果
*/

import java.util.Scanner;

public class t1 {
    public static void main(String[] args) {
        //键盘录入一个字符串,用 Scanner 实现
        System.out.println("请输入你要输入的数字:");
        String line=new Scanner(System.in).nextLine();

        //调用方法,用一个变量接收结果
        String s=reverse(line);
        //输出结果
        System.out.println("s:"+s);
    }
    //定义一个方法,实现字符串反转
/*
两个明确:
返回值类型:String
参数:String s
*/
    private static String reverse(String s) {
        //在方法中把字符串倒着遍历,然后把每一个得到的字符拼接成一个字符串并返回
        String  ss=" ";
        for (int i=s.length()-1;i>=0; i--) {
            ss=ss+s.charAt(i);
        }
        return ss;
    }
}


public boolean equals(Object anObject) 比较字符串的内容,严格区分大小写(用户名和密码) 
public char charAt(int index) 返回指定索引处的 char 值 
public int length() 返回此字符串的长度

StringBuilder 是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是 StringBuilder 对象中的 内容是可变的。

String类:内容是不可变的 
StringBuilder类:内容是可变的

public StringBuilder() 创建一个空白可变字符串对象,不含有任何内容 
public StringBuilder(String str) 根据字符串的内容,来创建可变字符串对象

5、分割相关法
/*
分割字符串的方法:
public String[] split(String regex):按照参数的规则,将字符串分割成为若干部份。
注意事项:
split方法的参数其实是一个正则表达式,今后学习。
今天要注意:如果按照英文据点“.”进行分割,必须写“\\.”
*/
public class t5 {
    public static void main(String[] args) {
String str1="aaa,bbbb,ssss";
String[] array1=str1.split(",");
        for (int i = 0; i <array1.length ; i++) {
            System.out.println(array1[i]);
        }
        System.out.println("============");
        

        String str2="aaaaa  aaaa  ssssss";
        String[] array2=str2.split("  ");
        for (int i = 0; i < array2.length; i++) {
            System.out.println(array2[i]);
        }
         System.out.println("============");
         String str3="aaaaa.aaaa.ssssss";
        String[] array3=str3.split("\\.");
        for (int i = 0; i < array3.length; i++) {
            System.out.println(array3[i]);
        }
    }
}

StringBuilder类

 

public StringBuilder append (任意类型) 添加数据,并返回对象本身

public StringBuilder reverse() 返回相反的字符序列

public int length() 返回长度,实际存储值

public String toString() 通过toString()就可以实现把StringBuilder转换为String

 

StringBuilder 是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是 StringBuilder 对象中的 内容是可变的。

 

常用的构造方法

public StringBuilder(): 创建一个空白可变字符串对象,不含有任何内容

public StringBuilder(String str) :根据字符串的内容,来创建可变字符串对象

 

  public class StringBuilderDemo01 {
        public static void main(String[] args) {
//public StringBuilder():创建一个空白可变字符串对象,不含有任何内容
            StringBuilder sb = new StringBuilder();
            System.out.println("sb:" + sb);
            System.out.println("sb.length():" + sb.length());
//public StringBuilder(String str):根据字符串的内容,来创建可变字符串对象
            StringBuilder sb2 = new StringBuilder("hello");
            System.out.println("sb2:" + sb2);
            System.out.println("sb2.length():" + sb2.length());
        }
    }

StringBuilder类添加和反转方法

添加和反转方法

public StringBuilder append(任意类型): 添加数据,并返回对象本身

public StringBuilder reverse() :返回相反的字符序列

 public class StringBuilderDemo01 {
        public static void main(String[] args) {
//创建对象
            StringBuilder sb = new StringBuilder();
//public StringBuilder append(任意类型):添加数据,并返回对象本身
// StringBuilder sb2 = sb.append("hello");
//
// System.out.println("sb:" + sb);
// System.out.println("sb2:" + sb2);
// System.out.println(sb == sb2);
// sb.append("hello");
// sb.append("world");
// sb.append("java");
// sb.append(100);
//链式编程
            sb.append("hello").append("world").append("java").append(100);
            System.out.println("sb:" + sb);
//public StringBuilder reverse():返回相反的字符序列
            sb.reverse();
            System.out.println("sb:" + sb);
        }
    }

StringBuilder和String相互转换

StringBuilder转换为String

public String toString():通过 toString() 就可以实现把 StringBuilder 转换为 String

String转换为StringBuilder

public StringBuilder(String s):通过构造方法就可以实现把 String 转换为 StringBuilder

 

 public class StringBuilderDemo02 {
        public static void main(String[] args) {
/*
//StringBuilder 转换为 String
StringBuilder sb = new StringBuilder();
sb.append("hello");
//String s = sb; //这个是错误的做法
//public String toString():通过 toString() 就可以实现把 StringBuilder 转换为
String
String s = sb.toString();
System.out.println(s);
*/
//String 转换为 StringBuilder
            String s = "hello";
//StringBuilder sb = s; //这个是错误的做法
//public StringBuilder(String s):通过构造方法就可以实现把 String 转换为StringBuilder
            StringBuilder sb = new StringBuilder(s);
            System.out.println(sb);
        }
    }

字符串拼接升级版案例
    /*
    思路:
    1:定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
    2:定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回。
    返回值类型 String,参数列表 int[] arr
    3:在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回
    4:调用方法,用一个变量接收结果
    5:输出结果
    */
    public class StringBuilderTest01 {
        public static void main(String[] args) {
//定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
            int[] arr = {1, 2, 3};
//调用方法,用一个变量接收结果
            String s = arrayToString(arr);
//输出结果
            System.out.println("s:" + s);
        }
        //定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回
/*
两个明确:
返回值类型:String
参数:int[] arr
*/
        public static String arrayToString(int[] arr) {
//在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for(int i=0; i<arr.length; i++) {
                if(i == arr.length-1) {
                    sb.append(arr[i]);
                } else {
                    sb.append(arr[i]).append(", ");
                }
            }
            sb.append("]");
            String s = sb.toString();
            return s;
        }
    }


定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果 例如,键盘录入abc,输出结果 cba
 /*
    思路:
    1:键盘录入一个字符串,用 Scanner 实现
    2:定义一个方法,实现字符串反转。返回值类型 String,参数 String s
    3:在方法中用StringBuilder实现字符串的反转,并把结果转成String返回
    4:调用方法,用一个变量接收结果
    5:输出结果
    */
    public class StringBuilderTest02 {
        public static void main(String[] args) {
//键盘录入一个字符串,用 Scanner 实现
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入一个字符串:");
            String line = sc.nextLine();
//调用方法,用一个变量接收结果
            String s = myReverse(line);
//输出结果
            System.out.println("s:" + s);
        }
        //定义一个方法,实现字符串反转。返回值类型 String,参数 String s
/*
两个明确:
返回值类型:String
参数:String s
*/
        public static String myReverse(String s) {
//在方法中用StringBuilder实现字符串的反转,并把结果转成String返回
//String --- StringBuilder --- reverse() --- String
// StringBuilder sb = new StringBuilder(s);
// sb.reverse();
// String ss = sb.toString();
// return ss;
            return new StringBuilder(s).reverse().toString();
        }
    }

10.4 静态static

 

1、静态static关键字修饰成员变量

 

public class Student {
    private int id;
    private String name;
    private int age;
     static String room ;
    private static int idCounter=0;//学号计数器,每当new了一个新对象的时候,计数器++

    public Student() {
        idCounter++;
    }

    public Student(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        this.id=++idCounter;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

/*
如果一个变量使用了static关键字,那么这个变量不在属于对象自己,而是属于所在的类。多个对象共享同一份数据
 */
public class Demo01Static {
    public static void main(String[] args) {
        Student two=new Student("黄蓉",16);
        two.room="001教室";
        System.out.println("姓名:"+two.getName()+",学号:"+two.getId()
                +",年龄:"+two.getAge()+", 教室:"+two.room);
        Student one=new Student("郭靖",18);
        System.out.println("姓名:"+one.getName()+",学号:"+one.getId()
                +",年龄:"+one.getAge()+", 教室:"+one.room);

//        Student two=new Student("黄蓉",16);
//        two.room="001教室";
//        System.out.println("姓名:"+two.getName()+",学号:"+two.getId()
//                +",年龄:"+two.getAge()+", 教室:"+two.room);

    }
}

2、静态static关键字修饰成员方法

 

/*
一旦使用static修饰成员方法,那么这就成为了静态方法。静态方法不属于对象,而是属于类的。
如果没有static关键字,那么必须首先创建对象,然后通过对象才能使用它。
如果有static关键字,那么不需要创建对象,直接就能通过类名称来使用它。

无论是成员变量,还是成员方法。如果有了static,都推荐按使用类名称进行调用。
静态变量:类名称.静态变量
静态方法:类名称.静态方法()

注意事项:
1.静态不能直接访问非静态。
原因:因为在内存中是【先】有的静态内容,【后】有的非静态内容
”先人不知道后人,但是后人知道先人“
2.静态方法当中不能用this
原因:this代表当前对象,通过谁调用的方法,谁就是当前对象

 */
public class Demo02myclass {
    public static void main(String[] args) {
        MyClass obj=new MyClass();//创建对象
        //然后才能使用没有static关键字的内容
        obj.method();

        //对于静态方法来说,可以通过对象名进行调用,,也可以直接通过类名称来调用
        obj.methodStatic();//正确,不推荐
        MyClass.methodStatic();//正确,推荐

        //对于本来当中的静态方法,可以省略类名称
        myMethod();
        Demo02myclass.myMethod();//完全等效
    }

    private static void myMethod() {
        System.out.println("自己的方法");
    }
}

public class MyClass {

    int num;//成员变量
    static int numStatic;//静态变量

    //成员方法
    public void method(){
        System.out.println("这是一个成员方法");
        //成员方法可以访问成员变量
        System.out.println(num);
        //成员方法可以访问静态变量
        System.out.println(numStatic);
    }
    public static void methodStatic(){
        System.out.println("这是一个静态方法");
        //静态方法可以访问静态变量
        System.out.println(numStatic);
        //静态不能直接访问非静态【重点】
        //System.out.println(num);//错误方法

        //静态方法中不能使用this
        System.out.println(this);//错误写法

    }
}

 

 

 

 

/*
静态代码块的格式是:
public class 类名称{
static{
//静态代码块的内容
}
}
特点:当第一次用到本类是,静态代码块执行唯一的一次
静态内容总是优先于非静态,所以静态代码块比构造方法先执行.

静态代码块典型用途:
用来一次性地对非静态变量赋值。
 */
public class t6 {
    public static void main(String[] args) {
Person one =new Person();
        Person two =new Person();
    }
}

public class Person {
    static{
        System.out.println("静态代码块执行");
    }
    public Person(){
        System.out.println("构造方法执行!");
    }
}

10.5 数组工具类Arrays

 

/*
java.util.Arrays是一个与数组相关的工具类,里面提供了大量静态方法,用来实现数组常见的操作。
public static String toString(数组):将参数数组变成字符串(按照默认格式:[元素1,元素2,。。。。])

public static void sort(数组):按照默认升序(从小到大)对数组的元素进行排序。
备注:
1.如果是数值,sort默认按照升序从小到大。
2.如果是字符串,sort默认按照字母升序。
3.如果是自定义的类型,那么这个定义的类型需要用Comparable或者Comparator接口的支持。(今后学习)
4.
 */
public class t7 {
    public static void main(String[] args) {
        int [] array={10,20,30};

        //将int[]数组按照默认格式变成字符串
        String str= Arrays.toString(array);
        System.out.println(str);//[10, 20, 30]
        int[] array1={2,3,4,5,9};
        Arrays.sort(array1);
        System.out.println(Arrays.toString(array1));//[2, 3, 4, 5, 9]
    }
}

10.6 数学工具类Math

 

/*
java.util.Math类是数学相关的工具类,里面提供了大量的静态方法,完成与数学运算相关的操作

public static double abs(double num):获取绝对值
public static double ceil(double num):向上取整
public static double floor(double num):向下取整
public static long round(double num):四舍五入

Math.PI:代表近似的圆周率常量。
 */
public class t8 {
    public static void main(String[] args) {
        //获取绝对值
        System.out.println(Math.abs(3.14));//3.14
        System.out.println(Math.abs(0));//0
        System.out.println(Math.abs(-0.52));//0.52
        System.out.println("=============");

        //向上取整
        System.out.println(Math.ceil(3.9));//4.0
        System.out.println(Math.ceil(3.1));//4.0
        System.out.println("=============");

        //向下取整
        System.out.println(Math.floor(3.9));//3.0
        System.out.println(Math.floor(3.1));//3.0
        System.out.println("=============");

        //四舍五入
        System.out.println(Math.round(3.5));//4
        System.out.println(Math.round(3.1));//3
    }
}

十一、继承

 

 

 

继承的概念

继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及 追加属性和方法

11.1 继承的格式

继承通过extends实现

格式:class 子类 extends 父类 { }

举例:class Dog extends Animal { }

 

继承带来的好处

继承可以让类与类之间产生关系,子父类关系,产生子父类后,子类则可以使用父类中非私有的成员。

 

 

 

 

11.2 继承中成员变量的访问

public class Fu {
    public void show(){
        System.out.println("show方法调用");
    }
}

public class Zi extends Fu{
    public void method(){
        System.out.println("method方法调用");
    }
}


public class Demo01ExtendsFile {
    public static void main(String[] args) {
        //创建对象,调用方法
        Fu f=new Fu();
        f.show();//只调用父类对象,没有任何子类内容

        Zi z=new Zi();
        z.method();//method方法调用
        z.show();//show方法调用
    }
}

 

11.3 区分子类方法中重名的三种变量

 

this:代表本类对象的引用

super:代表父类存储空间的标识(可以理解为父类对象引用)

 

成员变量:

this.成员变量 - 访问本类成员变量

super.成员变量 - 访问父类成员变量 成员方法: this.成员方法 - 访问本类成员方法

super.成员方法 - 访问父类成员方法

构造方法:

this(…) - 访问本类构造方法

super(…) - 访问父类构造方法

 

/*

局部变量: 直接写成员变量名

本类的成员变量: this.成员变量名

父类的成员变量: super.成员变量名

*/

public class Fu {
    int num=10;
}

public class Zi extends Fu{
    int num=20;
    public void method(){
        int num=30;
        System.out.println(num);//30,局部变量
        System.out.println(this.num);//20,本类的成员变量
        System.out.println(super.num);//10,父类的成员变量
    }
}


public class Demo04 {
    public static void main(String[] args) {
        Zi zi=new Zi();
        zi.method();

    }
}

 

11.4 继承中成员方法的访问特点

/*

在父子类的继承关系当中,创建子类对象,访问成员方法的规则:

创建的对象是谁,就优先用谁,如果没有则向上找。

注意事项:

无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。

 

重写(Override)

概念:在继承关系当中,方法的名称一样,参数列表也一样。

 

重写(Override):方法的名称一样,参数列表【也一样】。覆盖、覆写

重写(Overload):方法的名称一样,参数列表【不一样】。

 

方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。

*/

 

public class Fu {
    public void methodFu(){
        System.out.println("父类方法执行!");
    }
}

public class Zi extends Fu{

    public void methodZi() {
        System.out.println("子类方法执行");
    }

    public void method() {
        System.out.println("子类重名方法执行");
    }
}


public class Demo05 {
    public static void main(String[] args) {
        Zi zi=new Zi();

        zi.methodFu();
        zi.methodZi();

        //创建的是new了子类对象,所以优先用子类方法
        zi.method();
    }
}

11.5 继承中方法的覆盖重写

方法覆盖重写的注意事项:

 

1.必须保证父子类之间方法的名称,参数列表也相同

@Override:写在方法前面,用来检测是不是有效的正确覆盖重写

这个注释就算不写,只要满足要求,也是正确的方法覆盖重写

2.子类方法的返回值必须【小于等于】父类方法的返回值范围。

前提:java.lang.Object类是所有类的公共最高父类(祖宗类),

java.lang.String就是Object的子类

3.子类方法的权限必须【大于等于】父类方法的权限修饰符。

小扩展提示:public > protected > (default) > private

备注:(default)不是关键字default,而是什么都写,留空

 

public class Fu {

    public Object method(){
        return null;
    }
}

public class Zi extends  Fu{

    @Override
    public Object method(){
        return null;
    }
}


public class demo06Override {
    public static void main(String[] args) {

    }
}
//老款手机
public class Phone {
    public static void call(){
        System.out.println("打电话");
    }
    public static void send(){
        System.out.println("发短信");
    }
    public void show(){
        System.out.println("显示号码");
    }
}

//定义一款新手机,使用老手机作为父类
public class NewPhone extends Phone{
@Override
    public void show() {
        //把父类的show方法拿过来
        super.show();
        System.out.println("显示号码");
        System.out.println("显示姓名");
        System.out.println("显示头像");
    }
}


public class Demo06Phone {
    public static void main(String[] args) {
        Phone phone=new Phone();

        phone.call();
        phone.send();
        phone.show();
        System.out.println("==========");

        NewPhone newPhone=new NewPhone();
        newPhone.call();
        newPhone.send();
        newPhone.show();
    }
}

11.6 继承中构造方法的访问特点

/*

继承关系中,父子类构造方法的访问特点:

 

1.子类构造方法中有一个默认隐含的super()调用,所以一定是先调用的父类构造,后执行的是子类构造。

2.子类构造可以通过super关键字来子类构造调用父类重载构造。

3.super的父类构造调用,必须是子类构造方法的第一个语句,不能一个子类构造调用多次super构造。

总结:

子类必须调用父类构造方法,不写则赠送super();写了则用写的指定的super调用,super只能有一个,还必须是第一个

*/

public class Fu {
    public Fu(){
        System.out.println("父类无参构造");
    }
    public Fu(int num){
        System.out.println("父类构造方法!");
    }
public class Zi extends Fu{
public  Zi(){
    //super();//再调用父类无参构造方法
    super(20);
    System.out.println("子类构造方法!");
}
public void method(){
    //super();//错误写法!只有子类构造方法,才能调用父类构造方法
}
}


public class Demo07 {
    public static void main(String[] args) {
        Zi zi=new Zi();

    }
}

11.7 super关键字三种用法

/*
super关键字的用法有三种:
1.在子类的成员方法中,访问父类的成员变量。
2.在子类的成员方法中,访问父类的成员方法
3.在子类的构造方法中,访问父类的构造方法

 */
public class Zi extends Fu{
    int num=20;

    public  Zi(){
        super();
    }
    public void methodZi(){
        System.out.println(super.num);//父类中的num
    }
    public void method(){
        super.method();//访问父类
        System.out.println("子类方法");
    }

public class Fu {
    int num=10;
    public void method(){
        System.out.println("父类方法");
    }
}

11.8 this关键字三种用法

super关键字用来访问父类内容,而this关键字用来访问本类内容。用法三种:

1.在本类的成员方法中,访问本类的成员变量.

2.在本类的方法中,访问本来的另一个成员方法

3.在本类的构造方法中,访问本类的另一个构造方法

在第三种用法当中要注意:

A.this(...)调用也必须是构造方法的第一个语句,唯一一个。

B.super和this两种构造方法,不能同时使用。

 

public class Zi extends Fu{
    int num=19;

    public Zi(){
        //super();//这一行不再赠送
    this(20);//本类中的无参构造,调用本类的有参构造
        //this(1,2);//错误写法
}
    public Zi(int n){

    }
    public Zi(int n,int m){

    }
    public void showNum(){
        int num=20;
        System.out.println(num);//局部变量
        System.out.println(this.num);
        System.out.println(super.num);
    }

    public  void methodA(){
        System.out.println("aaaaaa");
    }
    public  void methodB() {
        this.methodA();
        System.out.println("bbbb");
    }
    }



public class Fu {
    int num=10;

    public void method(){
        System.out.println("父类方法");
    }
}


public class Zi extends Fu{
    int num=20;

    @Override
    public void method(){
        super.method();//调用父类方法
        System.out.println("子类方法");
    }

    public void show(){
        int num=30;
        System.out.println(num);//30
        System.out.println(this.num);//20
        System.out.println(super.num);//10
    }
}


public class demo {
    public static void main(String[] args) {
        Zi zi=new Zi();

        zi.show();

        zi.method();
    }
}

1.第一步运行main,然后是方法。
2.new都在对当中。

11.9 Java继承的三个特点

Java语言是单继承的。

一个类的直接父类只能有唯一一个。

 

 

 

 

 

 

 

11.10 抽象

 

 

1、抽象方法和抽象类的格式

/*

抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束.

抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可。

 

如何使用抽象类和抽象对象:

1.不能直接创建new抽象类对象。

2.必须用一个子类来继承抽象父类。

3.子类必须覆盖重写抽象父类当中所有的抽象方法。

覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号。

*/

 

public abstract class Animal {
    //这是一个抽象方法,代表吃的东西,但是具体吃什么(大括号的内容)不确定。
    public abstract void eat();

    //这是普通的成员方法
   // public void method(){

    //}
}

public class demo11 {
    public static void main(String[] args) {
        Cat cat=new Cat();
        cat.eat();
    }
}


public class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}


2、抽象方法和抽象类的使用
public class Zi extends Fu{

    public Zi(){
        System.out.println("子类构造方法执行!");
    }

    //Alt+回车:自动生成
    @Override
    public void eat() {
        System.out.println("吃饭饭");

    }
}


public abstract class Fu {
    public Fu(){
        System.out.println("抽象父类构造方法执行!");
    }
    public abstract void eat();
}


public class demo12 {
    public static void main(String[] args) {
        Zi zi=new Zi();
        zi.eat();
    }
}

3、抽象方法和抽象类的注意事项
public class User {
    private String name;
    private int money;

    public User(){

    }

    public User(String name,int money){
        this.name=name;
        this.money=money;
    }

    //显示一下当前用户有多少钱
    public void show(){
        System.out.println("我叫:"+name+",我有多少钱:"+money);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }
}


//群主类
public class Manager extends User {

    public Manager() {
        //super(); //默认在里面
    }

    public Manager(String name, int money) {
        super(name, money);
    }

    //ArrayList:数组列表 ;  Integer:整数
    public ArrayList<Integer> send(int totalMoney, int count) {
        //首先需要一个集合,用来存储若干个红包的金额
        ArrayList<Integer> redList = new ArrayList<>();

        //首先看一下群主自己有多少钱
        int leftMoney = super.getMoney();//群主当前余额
        if (totalMoney > leftMoney) {
            System.out.println("余额不足");
            return redList;//返回空集合
        }

        //扣钱,其实就是重新设置余额
        super.setMoney(leftMoney - totalMoney);

        //发红包需要平均分成count份
        int avg = totalMoney / count;
        int mod = totalMoney % count;//余数,也就是甩下的零头
        //出不开的零头,包在最后一个红包当中
        //下面把红包一个一个放到集合当中
        for (int i = 0; i < count-1; i++) {
            redList.add(avg);
            //System.out.println();
        }
        //最后一个红包
        int last=avg+mod;
        redList.add(last);
        return redList;

    }

}


//普通成员
public class Member extends User{

    public Member() {
    }

    public Member(String name, int money) {
        super(name, money);
    }

    public void receive(ArrayList<Integer> list){
        //从多个红包当中随便抽取一个,给自己
        //随机获取一个集合当中的索引编号
        int index=new Random().nextInt(list.size());
        //根据索引,从集合当中删除,并得到被删除的红包,给自己
        int delta=list.remove(index);
        //当前成员自己本来有多少钱
        int money=super.getMoney();
        //加法,并且重新设置回去
        super.setMoney(money+delta);
    }
}


public class RedMain {
    public static void main(String[] args) {
        Manager manager=new Manager("群主",100);

        Member one=new Member("成员A",0);
        Member two=new Member("成员B",0);
        Member three=new Member("成员C",0);

        manager.show();//100
        one.show();//0
        two.show();//0
        three.show();//0
        System.out.println("==========");

        //群主总共发20块钱,分成3个红包
        ArrayList<Integer> redList=manager.send(20,3);
        //三个普通成员收红包
        one.receive(redList);
        two.receive(redList);
        three.receive(redList);

        manager.show();//100-20=80
        //6,6,8随机分成三人
        one.show();
        two.show();
        three.show();
    }
}

十二、接口

接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。

Java中的接口更多的体现在对行为的抽象!

 

基础知识:

1.类继承(extends)类,接口继承接口,类实现(implements)接口

2.接口没有方法体,只能声明函数

3.一个类可以实现多个接口,只能继承一个类

4.类必须重写接口的所有方法,不必须重写父类的所有方法

5.复杂关系:若接口A  extends 接口B(根据1),则接口A不必须重写接口B(根据4)。

     若类a implements A,则a必须要重写接口A和接口B所有的方法

     若类b implements B,类a extends 类b,所以a的父类b已经实现了B的所有方法,那么a只必须要重写A的所有方法就可以了

 

举例:

接口A——UserService     类a——UserServiceImpl

 

接口B——BaseDao    类b——AbstractDao

 

12.1 接口的定义基本格式

接口用关键字interface修饰

备注:换成了关键字interface之后,编译生成的字节码文件仍然是:抽象方法。

 

java 7,接口包含内容

1.常量

2.抽象方法

java 8,接口额外包含内容

3.默认方法

4.静态方法

java 9,接口额外包含内容

5.私有方法

 

接口使用步骤:

1.接口不能直接使用,必须有一个“实现类”来“实现”该接口

格式:

public class 类名 implements 接口名 {}

2.接口的实现类必须覆盖重写(实现)接口中所有的抽象方法

实现:去掉abstract关键字,加上方法体大括号。

3.创建实现类的对象,进行使用

 

注意事项:

如果实现类并没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类。

public interface 接口名 { //接口内容 }

类实现接口用implements表示

public class 类名 implements 接口名 {}

 

 

12.2 接口的抽象方法

1、接口的抽象方法定义

 

/*
在任何版本的Java中,接口都能定义抽象方法。
格式:
public abstract 返回值类型 方法名称(参数列表);

注意事项:
1.接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract
2.这两个关键字修饰符,可以选择性地省略。
 */
public interface MyInterface {

    //这是一个抽象方法
    public abstract void methodAbs1();

    //这也是抽象方法
    abstract void methodAbs2();

    //这也是抽象方法
    public void methodAbs3();

    //这也是抽象方法
    void methodAbs4();
}

2、接口的抽象方法使用
/*
在任何版本的Java中,接口都能定义抽象方法。
格式:
public abstract 返回值类型 方法名称(参数列表);

注意事项:
1.接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract
2.这两个关键字修饰符,可以选择性地省略。
 */
public interface MyInterface {

    //这是一个抽象方法
    public abstract void methodAbs1();

    //这也是抽象方法
    abstract void methodAbs2();

    //这也是抽象方法
    public void methodAbs3();

    //这也是抽象方法
    void methodAbs4();
}


public class MyInterfaceImpl implements MyInterface{
    @Override
    public void methodAbs1() {
        System.out.println("这是第一个方法!");
    }

    @Override
    public void methodAbs2() {
        System.out.println("这是第二个方法!");
    }

    @Override
    public void methodAbs3() {
        System.out.println("这是第三个方法!");
    }

    @Override
    public void methodAbs4() {
        System.out.println("这是第四个方法!");
    }
}


public class demo03Interface {
    public static void main(String[] args) {
        //错误写法!不能直接new接口对象使用。
//        MyInterface inter=new MyInterface();

        //创建实现类的对象使用
        MyInterfaceImpl impl=new MyInterfaceImpl();
        impl.methodAbs1();
        impl.methodAbs2();
    }
}


12.3 接口的默认方法定义和接口的默认方法使用
/*
从Java 8 开始,接口里允许定义默认方法。
格式:
public default 返回值类型 方法名称(参数列表){
方法体
}
备注:接口当中的默认方法,可以解决接口升级问题。
 */
public interface MyInterfaceDefault {

    //抽象方法
     public abstract  void methodAbs();

    //新添加了一个抽象方法
//    public abstract void methodAbs2();

    //新添加的方法,改成默认方法
    public default void methodDefault(){
        System.out.println("这是新添加的默认方法");
    }
}


public class MyInterfaceDefaultA implements MyInterfaceDefault{
    @Override
    public void methodAbs(){
        System.out.println("实现了抽象方法,AAA");
    }
}


public class MyInterfaceDefaultB implements MyInterfaceDefault{
    @Override
    public void methodAbs(){
        System.out.println("实现了抽象方法,BBB");
    }

    @Override
    public void methodDefault(){
        System.out.println("实现了类B覆盖重写了接口的默认方法");
    }
}


/*
1.接口的默认方法,可以通过接口实现类对象,直接调用。
2.接口的默认方法,也可以被接口实现类进行覆盖重写。
 */
public class demo04 {
    public static void main(String[] args) {
        //创建了实现类对象
        MyInterfaceDefaultA a=new MyInterfaceDefaultA();
        //调用抽象方法,实际运行的是右侧实现类
        a.methodAbs();//实现了抽象方法,AAA

        //调用默认方法,如果实现类当中没有,会向上找接口
        a.methodDefault();//这是新添加的默认方法
        System.out.println("=================");

        MyInterfaceDefaultB b=new MyInterfaceDefaultB();
        b.methodAbs();//实现了抽象方法,BBB
        b.methodDefault();//实现了类B覆盖重写了接口的默认方法
    }
}


12.4 接口的静态方法定义和接口的静态方法使用
/*
从Java 8 开始,接口里允许定义静态方法。
格式:
public static 返回值类型 方法名称(参数列表){
方法体
}
提示:就是将abstract或者static即可,带上方法体
 */
public interface MyInterfaceStatic {
    public static void methodStatic(){
        System.out.println("这是接口的静态方法!");
    }
}


public class MyInterfaceImpl implements MyInterfaceStatic {
}


/*
注意事项:
不能通过接口实现类的对象来调用接口当中的静态方法。
正确方法:
通过接口名称,直接调用其中的静态方法。
格式:
接口名称。静态方法名(参数);
 */
public class Demo05Interface {
    public static void main(String[] args) {
        //创建了实现类对象
        MyInterfaceImpl impl=new MyInterfaceImpl();

        //错误写法:impl.methodStatic();

        //直接通过接口名称调用静态方法
        MyInterfaceStatic.methodStatic();


    }
}


12.5 接口的私有方法使用
/*
问题描述:
我们需要抽取一个共有方法,用来解决两个默认方法之间重复代码问题。
但是这个共有方法不应该让实现类使用,应该是私有化的。
解决方案:
从Java 9开始,接口当中允许定义私有方法。
1.普通私有方法,解决多个默认方法之间重复代码问题
格式:
private 返回值类型 方法名称(参数列表){
方法体
}
2.静态私有方法,解决多个静态方法之间重复代码问题
格式:
private static 返回值类型 方法名称(参数列表){
方法体
}
 */
public interface MyInterPrivateA {
    public default void methodDefault1(){
        System.out.println("默认方法1");
        methodCommon();
    }
    public default void methodDefault2(){
        System.out.println("默认方法2");
        methodCommon();
    }
    public default void methodCommon(){
        System.out.println("AAAAAA");
        System.out.println("BBBBBB");
        System.out.println("CCCCCC");
    }
}


public class MyInterfacePrivateImpl implements MyInterPrivateA{
    public void methodAnother(){
    }
}


静态比较
public interface MyInterPrivateB {
    public static void methodStatic1(){
        System.out.println("静态方法1");
        methodStaticCommon();
    }
    public static void methodStatic2(){
        System.out.println("静态方法2");
        methodStaticCommon();
    }
    public /*private*/ static void methodStaticCommon(){
        System.out.println("AAAAAA");
        System.out.println("BBBBBB");
        System.out.println("CCCCCC");
    }
}


public class Demo06 {
    public static void main(String[] args) {

        MyInterPrivateB.methodStatic1();

        MyInterPrivateB.methodStatic2();
    }
}

12.6 接口的常量定义和使用

接口当中也可以定义”成员变量“,但是必须使用public static final 三个关键字。

从效果上看,这其实就是接口的【常量】。

格式:

public static final 数据类型 常量名称 = 数据值;

备注:

一旦使用final关键字进行修饰,说明不可改变。

 

注意:

一旦使用final关键字进行修饰,说明不可改变。

 

1.接口当中的常量,可以省略public static final ,注意:不写也照样写这样。

2.接口当中的常量,必须进行赋值:不能不赋值。

3.接口当中常量的名称,使用完全大写的字母,用下划线进行分割。

 

public interface MyInterfaceConst {

    //这其实就是一个常量,一旦赋值,不可修改
    public static final int NUM=10;//final:最终的
}

public class Demo05Interface {
    public static void main(String[] args) {
        //访问接口当中的常量
        System.out.println(MyInterfaceConst.NUM);
    }
}

12.7 接口内容小结

 

12.8 继承父类并实现多接口

 

使用接口的时候,需要注意:

1.接口是没有静态代码块或者构造方法的

2.一个类的直接父类是唯一的,但是一个类可以同时实现多个接口

格式:

public class MyInterfaceImpl implements MyInterfaceA,MyInterfaceB{

//覆盖重写所有抽象方法

}

3.如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要重盖覆写一次即可。

4.如果实现类没有覆盖重写所有接口当中的所有抽象方法。

5.如果实现类锁实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。

6.一个类如果直接父类当中的方法,和接口当中的默认方法产生冲突,优先用父类当中的方法。

public interface MyInterfaceA {
    public abstract void methodA();
    
    public abstract void methodAbs();

    public default void methodDefault(){
        System.out.println("默认方法AAA");
    }
}

public interface MyInterfaceB {

    public abstract void methodB();

    public abstract void methodAbs();

    public default void methodDefault(){
        System.out.println("默认方法BBB");
    }
}


public  abstract class MyInterfaceAbstract 
implements  MyInterfaceA,MyInterfaceB{

    @Override
    public void methodA() {

    }

//    @Override
//    public void methodB() {
//
//    }

    @Override
    public void methodAbs() {

    }
    @Override
    public void methodDefault() {

    }
}


public class MyInterfaceImple/*extends Object*/ 
implements MyInterfaceA,MyInterfaceB {

    @Override
    public void methodA() {
        System.out.println("覆盖重写了A方法");
    }

    @Override
    public void methodAbs() {
        System.out.println("覆盖重写了A、B接口都有的(Abs)抽象方法");
    }

    @Override
    public void methodDefault() {
        System.out.println("对多个接口当中冲突的默认方法进行覆盖重写");
    }

    @Override
    public void methodB() {
        System.out.println("覆盖重写了B方法");
    }

}


public interface MyInterface {
    public default void method(){
        System.out.println("接口的默认方法");
    }
}


public class Fu {
    public void method(){
        System.out.println("父类方法");
    }
}


//继承优先于接口实现
public class Zi extends Fu implements MyInterface{

}


public class Demo02Interface {

    public static void main(String[] args) {
        Zi zi=new Zi();
        zi.method();
    }
}


12.9 接口之间的多继承
/*
1.类与类之间是单继承的。直接父类只有一个。
2.类与接口之间是多实现的。一个类可以实现多个接口。
3.接口与接口之间是多继承的。

注意事项:
1.多个父接口当中的抽象方法如果重复,没关系
2.多个父类接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写,【而且带着default关键字】。

 */
public class demo03Relations {

}


public interface MyInterfaceA {
    public abstract void menthodA();

    public abstract void menthodCommon();

    public default void methodDefault(){
        System.out.println("AAAA");
    }
}


public interface MyInterfaceB {
    public abstract void methodB();

    public abstract void menthodCommon();

    public default void methodDefault(){
        System.out.println("BBB");
    }
}


/*
这个子接口当中有有几个方法?答:四个。
menthodA:来源于接口A
menthodB:来源于接口B
menthodCommon:同时来源于接口A和B
menthod:来源于我自己
 */
public interface MyInterface extends MyInterfaceA,MyInterfaceB{
    public abstract void menthod();

    @Override
    default void methodDefault() {

    }
}


public class MyInterfaceImpl implements MyInterface{


    @Override
    public void menthod() {

    }

    @Override
    public void menthodA() {

    }

    @Override
    public void menthodCommon() {

    }

    @Override
    public void methodB() {

    }
}

 

十三、多态

什么是多态

同一个对象,在不同时刻表现出来的不同形态

多态的前提

要有继承或实现关系

要有方法的重写

要有父类引用指向子类对象

 

成员访问特点

成员变量

编译看父类,运行看父类

成员方法

编译看父类,运行看子类

13.1 多态的格式与使用

代码当中体现多态性,其实就是一句话:父类引用指向子类对象。

格式:

父类名称 对象名=new 子类名称();

或者:

接口名称 对象名=new 实现类名称();

 

public class Fu {
    public void method(){
        System.out.println("父类方法");
    }
    public void methodFu(){
        System.out.println("父类特有方法");
    }
}

public class Zi extends Fu{

    @Override
    public void method(){
        System.out.println("子类方法!");
    }

}


public class demo14 {
    public static void main(String[] args) {
        //使用多态的写法
        //左侧父类的引用,指向了右侧子类的对象
        Fu obj=new Zi();
        obj.method();
        obj.methodFu();
    }
}

13.2 成员变量的使用特点
public class Fu {

    int num=10;

    public void showNum(){
        System.out.println(num);
    }
}


public class Zi extends Fu{

    int num=20;

    int age=16;
}


/*
访问成员变量的两种形式:
1.直接通过对象名称访问成员变量,看等号右边是谁,优先用谁,没有则向上找。
2.间接通过成员方法访问成员变量,看该方法属于谁。优先用谁,没有则向上找。
 */
public class demo15 {
    public static void main(String[] args) {
        //使用多态的写法,父类引用指向子类对象
        Fu obj=new Zi();
        System.out.println(obj.num);//父:10
        System.out.println("============");
        //子类没有覆盖重写,就是父:10
        //子类有覆盖重写,就是子:20
        obj.showNum();
    }
}

13.3 成员方法的使用特点

在多态的代码当中,成员方法的访问规则是:

看new 的是谁,就优先用谁,没有则向上找。

 

口诀:

编译看左边,运行看右边。

 

对比一下:

成员变量:编译看左边,运行还看左边。

成员方法:编译看左边,运行看右边。

 

public class Fu {

    int num=10;

    public void showNum(){
        System.out.println(num);
    }
    public void method(){
        System.out.println("父类方法");
    }
    public void methodFu(){
        System.out.println("父类特有方法");
    }
}

public class Zi extends Fu{

    int num=20;

    int age=16;

    @Override
    public void showNum(){
        System.out.println(num);
    }
    @Override
    public void method(){
        System.out.println("子类方法");
    }
    //@Override
    public void methodZi(){
        System.out.println("子类特有方法");
    }
}


public class demo15Method {
    public static void main(String[] args) {

        Fu obj=new Zi();//多态

        obj.method();//父子都有,优先用子
        obj.methodFu();//子类没有,父类有,向上找到父类

        //编译看左边,右边是Fu,Fu当中没有methodZi方法,所以编译错误。
      //  obj.methodZi();//错误写法

    }
}

 

13.4 对象的转型

1、向上转型

 

public abstract class Animal {
    public  abstract void eat();
}

public class Cat extends Animal{
@Override
    public void eat(){
    System.out.println("猫吃鱼");
}
}


public class demo16 {
    public static void main(String[] args) {
        //对象的向上转型,就是:父类引用指向之类对象。
        Animal animal=new Cat();
        animal.eat();
    }
}

 

2、向下转型

 

 

public class Cat extends Animal{
@Override
    public void eat(){
    System.out.println("猫吃鱼");
}
    public void catchMouse() {
        System.out.println("猫抓老鼠");
}

}

public class Dog extends Animal{
    @Override
            public void eat(){
        System.out.println("狗吃屎");
    }

    public void watchHouse(){
        System.out.println("狗看家");
    }
}


public abstract class Animal {
    public  abstract void eat();
}


/*
向上转型一定是安全的,没有问题的,正确的。但是也有一个弊端:
对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。

解决方案:
用对象的向下转型【还原】
 */
public class demo16 {
    public static void main(String[] args) {
        //对象的向上转型,就是:父类引用指向之类对象。
        Animal animal=new Cat();//本来创建的时候是一只猫
        animal.eat();//猫吃鱼

      //  animal.catchMouse();//写法错误

        //向下转型,进行“还原”动作
        Cat cat=(Cat) animal;
        cat.catchMouse();//猫抓老鼠

        //向下是错误的向下转型
        //本来new的时候是一只猫,现在非要当作狗
        //错误写法!编译不会报错,但是运行会出现异常
        //java.long.ClassCastException. 类转换异常
        Dog dog=(Dog) animal;
    }
}


 用instanceof关键字进行类型判断
/*
如何才能知道一个父类引用的对象,本来是什么子类?
格式:
对象 instanceof 类名称
这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例

 */
public class demo16Instanceof {
    public static void main(String[] args) {
        //Animal animal=new Cat();//本来是一只猫
        Animal animal=new Dog();//本来是一只狗
        animal.eat();//猫吃鱼

        //如果希望调用子类特有方法,需要向下转型
        //判断一下父类引用animal本来是不是Dog
        if (animal instanceof Dog){
            Dog dog=(Dog) animal;
            dog.watchHouse();
        }

        //判断一下animal本来是不是Cat
        if (animal instanceof Cat){
            Cat cat=(Cat) animal;
            cat.catchMouse();
        }
      giveMePet(new Dog());
    }
    public static void giveMePet(Animal animal){
        if (animal instanceof Dog){
            Dog dog=(Dog) animal;
            dog.watchHouse();
        }

        if (animal instanceof Cat){
            Cat cat=(Cat) animal;
            cat.catchMouse();
        }
    }
}

13.6 笔记本USB接口案例

public interface USB {//interface接口
    public abstract void open();//打开设备;abstract:抽象
    public abstract void close();//关闭设备
}


public class Computer {
    public void powerOn(){
        System.out.println("笔记本电脑开机");
    }
    public void powerOff(){
        System.out.println("笔记本电脑关机");
    }
    //使用USB设备的方法,使用接口作为方法的参数
    public void usbDevice(USB usb){
        usb.open();//打开设备

        if (usb instanceof Mouse){
            //一定要先判断
            Mouse mouse=(Mouse) usb;//向下转型
            mouse.click();
        }else if (usb instanceof Keyboard){//先判断
            Keyboard keyboard=(Keyboard) usb;//向下转型
            Keyboard.type();
        }

        usb.close();//关闭设备
    }
}


//鼠标就是一个USB设备
public class Mouse implements USB{
    @Override
    public void open(){
        System.out.println("打开鼠标");
    }
    @Override
    public void close(){
        System.out.println("关闭鼠标");
    }
    public void click(){
        System.out.println("鼠标点击");
    }
}


//键盘就是一个USB设备
public class Keyboard implements USB{
    @Override
    public void open(){
        System.out.println("打开键盘");
    }
    @Override
    public void close(){
        System.out.println("关闭键盘");
    }
    public static void type(){
        System.out.println("键盘输入");
    }
}


public class demo17 {
    public static void main(String[] args) {
        //首先创建一个笔记本电脑
        Computer computer=new Computer();
        computer.powerOn();

        //准备一个鼠标,供电脑使用
 //       Mouse mouse=new Mouse();
        //首先进行向上转型
        USB usbMouse=new Mouse();
        //参数是USB类型,我正好传递进去的是USB鼠标
        computer.usbDevice(usbMouse);
        System.out.println("============");

        //创建一个USB键盘
        Keyboard keyboard=new Keyboard();//没有使用多态写法
        //方法参数是USB类型,传递进去的是实现类对象
        computer.usbDevice(keyboard);//正确写法!也发生向上转型
        //使用子类对象,匿名对象,也可以
        //computer.usbDevice(new keyboard());

        computer.powerOff();
        System.out.println("=======");

        method(10.0);//正确写法:double----->double
        method(10);//正确写法:int------>double
        int a=30;
        method(a);//正确写法:int------>double
    }
    public static void method(double num){
        System.out.println(num);
    }
}

13.7 final关键字

1、概念与四种用法

final关键字代表最终、不可改变的:

 

常见四种用法:

1.可以用来修饰一个类。

2.可以用来修饰一个方法

3.还可以用来修饰一个局部变量

4.还可以用来修饰一个成员变量

 

/*
当final关键字用来修饰一个类的时候,格式:
public final class 类名称{
//. . .
}
含义:当前这个类不能有任何的子类。(大太监)
注意:一个类如果是final的,那么其中所有的成员方法都无法进行覆盖重写(因为没儿子)
 */
public class MyClass /*extends Object*/{
    public void method(){
        System.out.println("方法执行!");
    }
}

2、用于修饰成员方法
/*
当final关键字用来修饰一个方法的时候,这时候就是最终方法,也就是不能被覆盖重写。
格式:
修饰符 final 返回值类型 方法名称(参数列表){
//方法体
}

注意事项:
对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾。
 */
 //抽象类的定义
public abstract class Fu {
    public final void method(){
        System.out.println("父类方法执行!");
    }
    //抽象方法的定义
    public abstract void methodAbs();
    
}


public class Zi extends Fu{

    @Override
    public void methodAbs(){

    }
    //错误写法!不能覆盖重写父类当中final的方法
//@Override
    //public void method(){
       // System.out.println("子类覆盖重写父类的方法!");
    //}
}


3、用于修饰局部变量
public class Student {
     private String name;

     public Student(){

     }

    public Student(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


public class demo01 {
    public static void main(String[] args) {
          int num1=10;
        System.out.println(num1);//10

        num1=20;
        System.out.println(num1);//20

        //一旦使用final用来修饰局部变量,那么这个变量就不能进行更改。
        //“一次赋值,终生不变”
        final int num2=200;
        System.out.println(num2);//200

        //正确写法!只要保证有唯一一次赋值即可
        final int num3;
        num3=30;
        System.out.println(num3);//30

        //对于基本类型来说,不可变说的是变量当中的数据不可改变。
        //对于引用类型来说,不可改变的是变量当中的地址值不可改变。
        Student stu1=new Student("赵丽颖");
        System.out.println(stu1);
        System.out.println(stu1.getName());//赵丽颖
        stu1=new Student("霍建华");
        System.out.println(stu1);
        System.out.println(stu1.getName());//霍建华
        System.out.println("========");
        final Student stu2=new Student("高圆圆");
        System.out.println(stu2);
        System.out.println(stu2.getName());//高圆圆
        stu2.setName("高圆圆圆圆圆");
        System.out.println(stu2.getName());//高圆圆圆圆圆
    }
}


4、用于修饰成员变量
/*
对于成员变量来说,如果使用final关键字修饰,那么这个变量也照样是不可变。
1.由于成员变量具有默认值,所以用了final之后必须手动赋值,不会再给默认值了。
2.对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值。二者选其一
3.必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值。

 */
public class Person {
    //private String name;
    private final String name;
    public Person() {
        name="关晓彤";
    }

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    //public void setName(String name) {
    //    this.name = name;
   // }
}


类名作为形参和返回值(应用) 
1、类名作为方法的形参 
方法的形参是类名,其实需要的是该类的对象 
实际传递的是该对象的【地址值】 
2、类名作为方法的返回值 
方法的返回值是类名,其实返回的是该类的对象 
实际传递的,也是该对象的【地址值】
public class Cat {
    public void eat(){
        System.out.println("猫吃鱼");
    }
}

public class CatOperator {
    public void useCat(Cat c){
        c.eat();
    }

    public Cat getCat(){
        Cat c=new Cat();
        return c;
    }
}

public class demo04 {
    public static void main(String[] args) {
        CatOperator co=new CatOperator();

        Cat c=new Cat();
        co.useCat(c);
        System.out.println("=========");

        Cat c2=co.getCat();
        c2.eat();
    }
}


抽象类作为形参和返回值 
方法的形参是抽象类名,其实需要的是该抽象类的子类对象 
方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
public abstract class Animal {
    public abstract void eat();
}


public class Cat extends Animal{
    @Override
    public void eat(){
        System.out.println("猫吃鱼");
    }
}


public class AnimalOperator {
    public void useAnimal(Animal a){
        a.eat();
    }
    public Animal getAnimal(){
        Animal a=new Cat();
        return a;
    }
}


public class demo05 {
    public static void main(String[] args) {
        AnimalOperator ao=new AnimalOperator();
        Animal a=new Cat();
        ao.useAnimal(a);
        System.out.println("=========");

        Animal a2=ao.getAnimal();
        a2.eat();
    }
}


接口作为形参和返回值 
方法的形参是接口名,其实需要的是该接口的实现类对象 
方法的返回值是接口名,其实返回的是该接口的实现类对象

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
### 回答1: JMU Java 03面向对象基础-01-构造函数和toString方法。 构造函数是一种特殊的方法,在创建对象时自动调用,用于初始化对象的状态。 toString方法是Java中的一个方法,它可以返回对象的字符串表示形式,方便调试和打印输出。 ### 回答2: 构造函数和toString()是Java语言中的两个重要概念,它们是面向对象编程中的基础知识。本文将从以下几个方面来回答该问题: 一、构造函数 构造函数是一种特殊的方法,用于创建对象并初始化该对象的属性。一个类可以有多个构造函数,每个构造函数可以接受不同的参数,从而实现不同的对象初始化方式。在Java中,构造函数的名称与类名称相同,它没有任何返回值,包括void。 有两种类型的构造函数,即默认构造函数和带参数构造函数。默认构造函数没有任何参数,Java自动为每个类提供一个默认的构造函数,它执行以下操作: 1、初始化类的属性。 2、如果类继承自其他类,则自动调用父类的构造函数。 如果一个类定义了带参数构造函数,则默认构造函数就不再自动提供。带参数构造函数可以自定义对象的初始化方式,提供不同的参数初始化对象的属性。带参数构造函数的声明格式为: public 类名(参数列表){ } 二、ToString()方法 toString()是对象类中的一个方法,它返回一个表示该对象的字符串。通常情况下,该字符串包括了对象的类名和属性值,以便于在需要时打印对象信息。 在Java中,如果没有显式地定义toString()方法,则默认使用Object类中的默认方法,该方法返回一个格式为“类名@哈希值”的字符串。但通常情况下,我们需要重新定义toString()方法,以便获取对象的更详细的信息,比如对象的属性。 对象类中重写toString()方法的格式如下: public String toString(){ } 值得注意的是,toString()方法可以被覆盖或者重新定义,但它必须返回一个字符串对象,否则将出现编译错误。 结论: 构造函数和toString()是Java面向对象编程中的两个基本概念,这两者的作用分别是为对象初始化和展示对象信息。在实际工作中,我们需要充分理解这两个概念的含义和用途,从而更好的利用Java面向对象编程方式。 ### 回答3: Java是一门面向对象的语言,构造函数和toString是面向对象编程中常用的两种方法之一。构造函数是用于创建对象的特殊方法,它可以在创建新对象时执行必要的初始化操作。而toString方法则是将对象转化为指定格式的字符串。在Java开发中,学习和熟练使用构造函数和toString方法对于编写高效,易于维护且易于阅读的代码非常重要。 首先,构造函数是一个类的特殊方法,它与类同名,并且不需要显式调用。当我们创建一个新对象时,构造函数被自动调用。在构造函数中,通常执行一些初始化操作,如为对象的属性赋初始值。构造函数可以根据参数列表的不同,有多个重载版本。这样,我们可以根据需要以不同的方式创建对象,并且可以灵活地控制对象的初始化过程。 其次,toString方法是将对象转化为字符串的常用方法之一。它通常在输出对象时调用,将对象的属性转化为字符串并输出。在自定义类中,我们可以自己实现toString方法来控制对象转换成字符串的格式。对于调试和日志记录等任务,toString方法非常有用。它可以方便地将对象的状态输出到控制台或日志文件中,便于我们了解程序的运行状态和调试程序。 在使用构造函数和toString方法时,我们需要注意一些问题。首先,构造函数应该执行必要的初始化操作,但不应该执行过多的计算或IO操作。因为构造函数执行的时间可能很长,这导致性能问题。其次,toString方法应该返回一个稳定的字符串。这样,我们在不同的场景下输出这个对象时,可以获得相同的输出。最后,我们需要为自己的类实现好构造函数和toString方法,以方便其他人阅读、使用和理解我们的代码。 总的来说,构造函数和toString方法是Java面向对象编程中重要的基础知识。它们是我们创建和操作对象不可或缺的工具。通过熟练掌握这两个方法,我们可以写出更加健壮和易于维护的代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唐曌

谢谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值