2022-02-23

Day1

Java语言平台的版本

-Java SE(标准版) 为开发普通桌面和商务程序提供解决方案 是Java ME 和 Java EE 的基础,可以完成一些桌面应用程序的开发
-Java ME (小型版) 为开发电子消费产品和嵌入式设备提供解决方案
-Java EE(企业版) 为开发企业环境下的应用程序提供一套解决方案,该技术主要包括Select,jsp,主要针对Web应用开发

Java语言的特点
简单性,解释性,面向对象,高性能,分布式处理,多线程,健壮性,动态,结构性,安全性,开源,跨平台(JVM相当于翻译,Java可以跨平台,JVM不可以跨平台,针对每个操作系统都有对应的JVM)

第一个程序HelloWorld

class HelloWord{
  public static void main(String[] args)   {
      System.out.println("hello,world");
    }
}

写程序的步骤

/*
  需求: 在控制台上输出Hello,World
  分析:
         1.要写一个Java程序,必须先定义一个类
         2.程序要想运行,必须有main函数
         3.输出一个语句必须用到输出语句
  实现:
         1.定义类用到class,后边跟类名
         2.main函数的格式是固定的
            public static void main(String[] args){
                表达式或语句
            }
         3.输出语句的格式是固定的
            System.out.println("hello,world");    "hello,world"内容可变
*/
//这是我的第一个程序,输出hello,world
class HelloWord{
   //定义main方法,main是程序的入口,被JVM自动调用
    public static void main(String[] args){
         //输出语句
        System.out.println("hello,world");
    }
}

Day2

原码反码和补码
     原码       反码       补码
正数  二进制     与原码相同     与原码相同
负数  二进制     将原码取反     将反码末位+1
负数将反码转换成原码需要先减一在取反

数据类型
数据类型分为基本数据类型和引用数据类型(类,接口,数组)
基本数据类型(4类8种)
         占用字节      范围
  整数
  byte       1     -128到127
  shor       2     -2的15次方到2的15次方-1
  int        4     -2的31次方到2的31次方-1
  long       8     -2的63次方到2的63次方-1
 浮点数  
  float      4     -3.043E38到3.403E38
  double      8     -1.798E308到1.798E308
 字符
  cha r     2
 布尔
 boolean      1
在定义Long或者Float类型的数据时,要在数据后边加L或F
整数默认的类型为Int,浮点数默认的为double
byte和short在定义的时候默认接收的是一个整数,如果不在自己的范围内就报错

命名规则

常见的命名规则:见名知意
        举例:我要定义一个学生类
            class Student {}
            class S{}
            
        包:其实就是文件夹,用于把相同的类名进行区分
            全部小写
        
            单级: zhangsan
            多级:cn.baidu
                    
        类或者接口:
            一个单词:单词的首字母必须大写
                举例:Student,Dog
            多个单词:每个单词的首字母必须大写
                举例:HelloWorld,StudentName
            
        方法或者变量:
            一个单词:单词的首字母小写
                举例:main,age
            多个单词:从第二个单词开始,每个单词的首字母大写
                举例:studentAge,showAllNames()
                
        常量:
            一个单词:全部大写
                举例:PI
            多个单词:每个字母都大写,用_隔开
                举例:STUDENT_MAX_AGE

默认数据类型转换
是从小的范围到大的范围进行转换
byte,short,char→int→long→folat→double
注意:byte,short,long不可以相互转换,在运算时默认转换成int进行运算
  运算过程种有范围大的数据类型,结果一定是范围大的数据类型
  例:3(int)+3.55(double)结果是6.55(double),赋值时一定要注意
强制数据类型转换
格式:目标数据类型 变量 =(目标数据类型)(被转换的数据);
 例: int a = (int)(3+3.2); 结果为6
注意:强制类型转换会损失精度,3+3.2应该等于6.2,但int只能取整数部分

//下列两个语句那个会编译报错,为什么
byte b1 = 3;
byte b2 = 4;
byte b;
b = b1 + b2;//会报错,在运算时,byte,short,char会转换成int类型进行运算,Int占4位,赋值给byte类型会报错
b = 3+4;//不会报错,先将3+4的运算结果算出来,再看运算结果是否在byte 数据范围内,若在,则不报错

//将130赋值给byteb是否有问题?如果想赋值应该怎么写?结果是多少?
byte b = 130;//会报错,因为byte的取值范围为-127到128
byte b = (byte)(130);//可以进行强制类型转换
//结果为-126
/*
  分析过程
    要想知道为什么结果为-126,就需要知道数据在计算机是如何进行运算的
    计算机中的数据是通过补码进行运算的
获取130的二进制,130为整数,默认占4个字节
00000000 00000000 0000000 10000010
这是130的原码,正数的原码反码补码都相同,所以这也是130的补码
byte b 为字节,默认占1位字节,要对130的补码进行截取
得到 10000010    这是补码,且第一位为0,所以为负数,将负数的补码转换成原码
得到11111110  即-126
*/

输出的几种形式

System.out.println("hello"+'a'+1);//结果为helloa1
System.out.println('a'+1+"hello");//结果为98hello
//因为字符串数据和其他数据做+,结果依旧是字符串类型
//这里的+不是加法运算,而是作为连接符
System.out.println("5+5="+5+5);//结果为5+5=55,"5+5="为字符串,所以+为连接符
System.out.println(5+5+"=5+5");//结果为10=5+5,从左到右进行运算

记住'a'的Ascll码为97,'A'的Ascll码为65,'0'的Ascll码为48

算数运算符


++,--运算符
单独使用时:
  放在变量前边和后边的用法是一样的
参入运算时:
  放在变量的前边时,先进行自增或自减,在参入运算
  放在变量的后边时,先参入运算,在进行自增或自减
作用:对变量进行自增1或者自减1

赋值运算符
=,+=,-=,*=,/=,%=
=是基本的赋值运算符,其他的是拓展的赋值运算符
  +=就是将左边和右边相加然后赋值给左边
  例:a += 3;就是将a+3的值赋值给a

//拓展的赋值运算符隐含了强制类型转
short s ;
s = s + 1;//会报错,因为short在运算时会转换成int类型,所以将int赋值给short是错误的
s+=1;//不会报错,拓展赋值运算符相当于 s = (s的数据类型)(s+1);进行强制类型转换

关系运算符
不管进行什么操作,结果一定是布尔类型


逻辑运算符
逻辑运算符用于连接布尔类型的表达式

&与 一假即假
|或 一真即真
^异或 相同为假,不同为真
&和&&的区别:
  &的左边为假时,则不对右边进行运算,直接忽略
  &&不管左边是否为假,右边都要进行运算
|与||同上

位运算符
直接对二进制进行运算,对数的补码进行操作
&与位运算:有0则0;|或位运算:有1则1;^位异或运算:相同为0,不同为1;
一个数与两个相同的数进行异或,结果不变
例:a ^ b ^ b; 结果为a
<<相当于把左边的数据乘以2的移动次幂,>>相当于把左边的数据除以2的移动次幂
操作时注意是对补码进行运算,换算成二进制是原码,注意负数;


 //交换两个整数的位置
int a = 10,b = 20;
//第一种方法,利用空变量进行交换(开发)
int c;
c = a;
a = b;
b = c;
//第二种方法,利用位异或实现(面试)
a = a ^ b;//不计算,直接带到下边
b = a ^ b;//b = a ^ b ^ b; 相当于 b = a;
a = a ^ b;// b = a ^ b ^ a;因为上边 b = a;
//第三种方法,利用变量加法
a = a+ b;//不计算,直接带入下边
b = a - b;// b = a + b - b;得 b = a 
a = a - b;// a = a + b - a 得 a = b
//第四种方法,一句话搞定
b = (a+b) - (a = b);//相当于把b赋给a,得到 b = (a+b) - b

优先级
口诀单目乘除为关系,逻辑三目后赋值。

Day3

三目运算符
格式:(关系表达式)?表达式1:表达式2;
如果表达式为真,则取表达式1的值,如果为假,则取表达式2的值

//求两个数中的最大值
int a = 3,b = 5;
int max = (a>b)?a:b;//如果a大于b,则把a的值给max,如果a不大于b,则把b的值给max

键盘录入数据
第一步导包:在所有的class定义之上
import java.util.Scanner;
第二步:创建对象:
Scanner sc = new Scanner(System.in);
第三步:接收数据:
int a = sc.nextInt();
nextInt只能获取Int类型的数,可以有nextFloat,nextDouble等

import java.util.Scanner;//导包
class Get Keyboard{
  public static void main(String[] agrs){
          Scanner sc = new Scanner(System.in);//创建对象sc
          int a;
          a = sc.nextInt();//用a接收键盘输入的数据
          System.out.println("从键盘获取的是"+a);
    }
}

流程控制语句
-顺序结构
-选择结构
-循环结构

顺序结构
最基本的流程控制,就是按照从上往下执行,先写的先执行

顺序结构图

选择结构
也称为分支结构,选择结构有特定的语法规则,代码要执行具体的逻辑运算进行判断,逻辑运算的结果有两个,所以产生选择,按照不同的选择执行不同的代码。
java提供了两种选择结构语句
-if语句
-switch语句

if语句
if语句有三种格式

/*
if语句第一种格式:
if(关系表达式) {
  语句体
}
执行流程
首先判断关系表达式看其结果是true还是false
如果是true就执行语句体
如果是false就不执行语句体
*/
int a = 20;
int b = 10;
if(a>b){  //先判断表达式a>b的结果是真还是假
  System.out.println("a大于b");//如果为真则执行输出语句,为假则不执行
}
if格式1流程图
/*
if语句第二种格式:
if(关系表达式) {
    语句体1;
}else {
   语句体2;
}
执行流程
首先判断关系表达式看其结果是true还是false
如果是true就执行语句体1
如果是false就执行语句体2
*/
int a = 20;
int b = 10;
if(a>b){  //先判断表达式a>b的结果是真还是假
  System.out.println("a大于b");//如果为真则执行if语句体,为假则输出else语句体
}else {
  System.out.println("b大于a");
}
if格式2流程图
/*
if语句第三种格式:
if(关系表达式1) {
    语句体1;
}else  if (关系表达式2) {
    语句体2;
}
    …
else {
    语句体n+1;
}
首先判断关系表达式1看其结果是true还是false
如果是true就执行语句体1
如果是false就继续判断关系表达式2看其结果是true还是false
如果是true就执行语句体2
如果是false就继续判断关系表达式…看其结果是true还是false
…
如果没有任何关系表达式为true,就执行语句体n+1

int a = 20;
int b = 10;
if(a>b){  //先判断表达式a>b的结果是真还是假
  System.out.println("a大于b");//为真则执行if语句体
}else if(b>a) {//为假则判断else if的表达式是真还是假
  System.out.println("b大于a");
}else {
  System.out.println("a等于b");
}
*/

if格式3流程图

if语句的使用场景
针对结果是boolean类型的判断
针对一个范围的判断
针对几个常量值的判断

switch语句

/*
switch语句格式:
switch(表达式) {
    case 值1:
       语句体1;
        break;
    case 值2:
       语句体2;
        break;
        …
    default:    
       语句体n+1;
       break;
}
*/

switch语句流程图

switch语句使用场景
针对几个常量值的判断

循环结构
循环语句的组成
初始化语句:
  一条或者多条语句,这些语句完成一些初始化操作
判断条件语句:
  这是一个boolean 表达式,这个表达式能决定是否执行循环体
循环体语句:
  这个部分是循环体语句,也就是我们要多次做的事情
控制条件语句:
  这个部分在一次循环体结束后,下一次循环判断条件执行前执行。通过用于控制循环条件中的变量,使得循环在合适的时候结束

for循环语句格式
格式:
for(初始化语句;判断条件语句;控制条件语句) {
  循环体语句;
}
执行流程
1.执行初始化语句
2.执行判断条件语句,看其结果是true还是false
  如果是false,循环结束
  如果是true,继续执行
3.执行循环体语句
4.执行控制条件语句
5.回到2继续

//用for循环求1-10的和
int num = 0,i;
for(i = 0;i < 10;i++){
  num = num +i;
}
System.out.println("1-10的和为"+num);

//求100-1000之间有哪些水仙花数
int i,x,y,z;  //水鲜花数是一种三位数,其各个数之立方和等于该数
for(i = 100;i < 1000;i++){
  x = i/100;  //125整除100,得1
  y = i/10%10;  //125整除10,得12然后在取余10得2,即125的十位
  z = i%10;  //125取余10得5
  if(i == x*x*x + y*y*y* +z*z*z){
      System.out.println("水仙花数"+i);
  }

}

for循环流程图

while循环语句
格式:
基本格式
while(判断条件语句) {
  循环体语句;
}

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


while循环流程图
//利用while循环求一张0.01M的纸折叠多少次可以超过珠穆朗玛峰8848M
double i = 0.01;
int j=0;//表示折叠的次数
while (i <= 8848){  //只要i小于8848就一直执行,直到i大于8848结束
    j++;
    i = i*2;
}
System.out.println("折叠了"+j+"次");

do while循环
格式:
基本格式
do {
  循环体语句;
}while((判断条件语句);

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

do while 循环最少会执行一次循环体,while,for则是必须条件为真才会执行


do while循环流程图

循环练习

/*
输出  *
      **
      ***
      ****
      *****
分析:输出5行*,依次增加数量
*/
for(int i = 0;i < 5;i++){  //控制外层循环5次
  for(int j = 0;j < i+1;j++){  //控制*输出的个数每次加1
    System.out.print("*");  //print 输出完不进行换行
  }
  System.out.println();  //println输出完进行换行,可以输出空进行换行
}

//输出九九乘法表
for (int i = 1; i < 10; i++) {  
    for (int j = 1; j < i+1; j++) {
        System.out.print(i+"*"+j+"="+i*j+"\t");
    }
System.out.println(" ");
}

跳转控制语句:break,continue,return
break:在switch结构和循环中使用,作用是跳出并结束本轮循环

for(int i = 0;i < 5;i++){
  if(i == 2){
      break;
  }
  System.out.print("你好");  //结果只输出两个你好,因为在i =2也就是第三次循环的时候,符合if的条件跳出
}

break跳出多层循环的用法
要想跳出多层循环,就必须带标签的跳出
标签的格式: 标签名:循环语句

for(int i = 0;i < 4;i++){
  for(int j = 0;j < 4;j++){
     System.out.print("*");  //输出一个四行四列的星号
     if(j == 2){
       break;                //加上break,输出四行三列的星号,因为if语句只是在j等于2的时候结束j的循环
     }
   }
System.out.println();  //换行
}
//要想退出多层循环就要用标签
out:
for(int i = 0;i < 4;i++){
  for(int j = 0;j < 4;j++){
    System.out.println("*");
    if(j == 2){
        break out;  //out:标签的作用就是break直接跳到out:处,且不在执行循环
      }
  }
  System.out.println();  //换行
}

continue:在循环中使用,作用是跳出本次循环,但继续执行下一次循环

for(int i = 1;i < 5;i++){
  if(i == 2){
    continue;  //输出结果为1,3,4,因为在i等于2的时候,符合if语句,所以跳出本次循环,但不结束循环
  }
  System.out.println(i);
}

continue也可以跳出多层循环,参考break;
return:不是为了跳转出循环体,更常用的功能是结束一个方法,也就是退出一个方法,跳转到上层调用的方法

Day4

方法
完成特定功能的代码块,其他语言称为函数
格式:
  修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2...) {
      方法体语句;
     return 返回值;
}

public static int sum(int a,int b){  
  int sum = a + b;
  return sum;
}

详细解释:
修饰符:目前就用 public static
返回值类型:就是功能结果的数据类型
方法名:符合命名规则即可。方便我们的调用
参数:
  实际参数:就是实际参与运算的
  形式参数;就是方法定义上的,用于接收实际参数的
参数类型:就是参数的数据类型
参数名:就是变量名
方法体语句:就是完成功能的代码
return:结束方法的。
返回值:就是功能的结果,由return带给调用者

要想写好一个方法,就必须明确两个东西:
 -返回值类型
   结果的数据类型
 -参数列表
   你要传递几个参数,以及每个参数的数据类型

方法调用格式(有返回值的):
 -单独调用:没意义
 -输出调用:写在输出语句中
 -赋值调用:调用后赋值给一个变量,方便后期使用
无返回值类型的只能单独调用
方法调用图解

方法调用过程

方法的注意事项:
 -方法不调用不执行
 -方法与方法是平级关系,不能嵌套定义
 -方法定义的时候参数之间用逗号隔开
 -方法调用的时候不用在传递数据类型
 -如果方法有明确的返回值,一定要有return带回一个值

方法重载
在同一个类中,方法名相同,参数列表不同,与返回值类型无关
参数列表不同:
 -参数个数不同
 -参数类型不同
方法重载特点
 -与返回值类型无关,只看方法名和参数列表
 -在调用时,虚拟机通过参数列表的不同来区分同名方法

public static void main(String[] args) {
       //方法重载,比较int和float数据是否相同
        int a = 3; 
        int b = 4;
        int c = 5;
        boolean flag = compare(a, b);  //根据给的参数的类型去匹配compare方法的类型
        System.out.println(flag);  //输出int false

        float f = 2.2f;
        float f1 = 2.2f;
        boolean flag1 = compare(f,f1);
        System.out.println(flag1);  //输出float true
    }
    public static boolean compare(int a,int b,int c){  //比较int
        System.out.println("int");
        return (a ==b);
    }
    public static boolean compare(float a,float b) {  //比较float
        System.out.println("float");
        return (a == b);
    }

数组
数组是存储同一种数据类型多个元素的集合,也可以看成是一个容器
数组既可以存储基本数据类型,也可以存储引用数据类型

数组定义:
-格式1:数据类型[] 数组名;

int [] arr;  

-格式2:数据类型 数组名[];

int arr [];

数组的初始化:
-动态初始化:初始化时只指定数组长度,由系统为数组分配初始值
格式:数据类型[] 数组名 = new 数据类型[数组长度];
数组长度就是数组中元素的个数

int [] arr = new int [5];  //定义了一个int类型的数组,这个数组可以存放3个int类型的值

-静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度
格式:数据类型[] 数组名 = new 数据类型[]{元素1,元素2,…};

int [] arr = new int []{1,2,3,4,5};
//可以简写为:
int [] arr = {1,2,3,4,5};

数组的长度可以用数组名.length表示
int [] arr = {1,2,3,4,5};
arr.length 就等于5
java的内存分配
Java 程序在运行时,需要在内存中的分配空间。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式
-栈 存储局部变量
-堆 存储new出来的东西
-方法区 (面向对象)
-本地方法区 (和系统相关)
-寄存器 (给CPU使用)

java内存分配图

数组遍历及输出

//数组的遍历及输出
int [] arr = {1,2,5,6,8,7,1,5};
    for (int i = 0; i < arr.length; i++) {
    System.out.println("第"+(i+1)+"个元素为"+arr[i]);
//求一个数在数组中第一次出现的位置
int [] arr = {1,2,5,6,8,7,1,5};
System.out.println("请输入一个数");
Scanner sc = new Scanner(System.in);  //在类上导包
int num = sc.nextInt();  //获取键盘数据
boolean flag = true;  //判断
    for (int i = 0; i < arr.length; i++) {
        if (num == arr[i]) {
            System.out.println("该数据首次出现在第" + (i + 1) + "个位置");
             flag = false;  //如果输入的数据在数组中,则把判断位变为flase
             break;
        }
     }
     if (flag){  //对判断位进行判断,若为真,则说明if语句未执行
     System.out.println("该数据没有在数组中");
    {

冒泡排序

//从小到大排列数组
int [] arr = {1,2,5,6,8,7,9,15};
int tmp = 0;  //中间变量
for (int i = 0; i < arr.length-1; i++) {  //外层循环控制比较次数,8个数需要7轮比较完
      for (int j = 0; j < arr.length-1; j++) {  //内层循环控制每次比较的次数,8个数需要7次比较
           if (arr[i] > arr[i+1]){  //如果前边的数比后边的数大,就换位置
               tmp = arr[i];  //中间变量,交换位置
               arr[i] = arr[i+1];
               arr[i+1] = tmp;
            }
       }
}
for (int i = 0; i < arr.length; i++) {
     System.out.print(arr[i]+" ");

数组常见错误
数组索引越界 ArrayIndexOutOfBoundsException
访问到了数组中的不存在的索引时发生

空指针异常 NullPointerException
数组引用没有指向实体,却在操作实体中的元素时

Day5

二维数组

格式1:
  数据类型[][] 数组名 = new 数据类型[m][n];
  m:表示这个二维数组有多少个一维数组
  n:表示每一个一维数组的元素有多少个
注意:
  以下格式也可以表示二维数组:
  -数据类型 数组名[][] = new 数据类型[m][n];
  -数据类型[] 数组名[] = new 数据类型[m][n];

class Array2 {
    public static void main(String[] args) {
         //定义一个二维数组
         int[][] arr = new int[3][2];
         //定义了一个二维数组arr
         //这个二维数组有3个一维数组的元素
         //每一个一维数组有2个元素
         //输出二维数组名称
         System.out.println(arr); //地址值 [[I@175078b
         //输出二维数组的第一个元素一维数组的名称
         System.out.println(arr[0]); //地址值  [I@42552c
         System.out.println(arr[1]); //地址值  [I@e5bbd6
         System.out.println(arr[2]); //地址值  [I@8ee016
         //输出二维数组的元素
         System.out.println(arr[0][0]); //0
         System.out.println(arr[0][1]); //0
    }
}

格式2:
  数据类型[][] 数组名 = new 数据类型[m][];
  m:表示这个二维数组有多少个一维数组
  列数没有给出,可以动态的给,这一次是一个变化的列数
格式3:
基本格式:
  数据类型[][] 数组名 = new 数据类型[][]{{元素1,元素2...},{元素1,元素2...},{元素1,元素2...}};
简化版格式:
  数据类型[][] 数组名 = {{元素1,元素2...},{元素1,元素2...},{元素1,元素2...}};
举例:
  int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
  int[][] arr = {{1,2,3},{4,5},{6}};

二维数组的遍历

public class Arr2Print {
    public static void main(String[] args) {
        //定义一个二维数组进行遍历
        int [] [] arr = {{1,2,3},{4,5},{6}};
        //利用每个数组的长度进行遍历
        for (int i = 0; i < arr[0].length; i++) {
            System.out.print(arr[0][i]+" ");
        }
        System.out.println();
        for (int i = 0; i < arr[1].length; i++) {
            System.out.print(arr[1][i]+" ");
        }
        System.out.println();
        for (int i = 0; i < arr[2].length; i++) {
            System.out.print(arr[2][i]+" ");
        }
        System.out.println();
        //可以用嵌套
        for (int i = 0; i < arr.length; i++) {  //arr.length代表二维数组的长度,也就是一维数组的个数
            for (int j = 0; j < arr[i].length; j++) { //arr[i].length代表每个一维数组的长度,i从0~2
                System.out.print(arr[i][j]+" ");
            }
            System.out.println();
        }
    }
}

打印杨辉三角

public class YangHui {
        /**
    需求:需求:打印杨辉三角形(行数可以键盘录入)
    1
    1 1 
    1 2 1
    1 3 3 1
    1 4 6 4 1 
    1 5 10 10 5 1
      分析:杨辉三角的第一列和最后一列都是1
            从第三行开始,每一个数据都是上一列的前一个数据和本列之和

     */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入行数");
        int m = sc.nextInt();
        int [][] arr= new int [m][m];
        for (int i = 0; i < arr.length; i++) {  //使第一列和最后一列都为1
            arr[i][0] = 1;
            arr[i][i] = 1;
        }
        //从第三行开始,每一个数据都是上一列的前一个数据和本列之和
        for (int i = 2; i < arr.length; i++) {  //从第三行开始,所以i= 2
            //因为第一列已经赋值了1,所以y从1开始
            //因为最后一列赋值了1,所以j

将一个整数的每一位写入到一个数组中

Scanner sc = new Scanner(System.in);
int num = sc.nextInt();  //从键盘获取一个数据
int index = 0;  //因为不知道获取了几位数,所以定义一个索引
while (num > 0){  //假设num12345,num = 1234,num = 123,num = 12,num = 1,num = 0,不符合循环条件
    arr[index] = num%10; //arr[0] = 5,arr[1] = 4,arr[2] = 3,arr[3] =2,arr[4] = 1
    num/=10;//num = 1234,num = 123,num = 12,num = 1,num = 0
    index++;//index = 1,index = 2,index = 3,index = 4,index =5,index为索引表示数组长度为5
}
//打印
for (int i = 0; i < index; i++) {  //index为索引,及数组长度
    System.out.print(arr[i]+" ");
//打印出5 4 3 2 1,但是数据是逆序存入数组的,可以在定义一个数组对arr进行逆序
public class Text1 {
    public static void main(String[] args) {
        /*
        * 某个公司采用公用电话传递数据信息,数据是小于8位的整数,为了确保安全,
    在传递过程中需要加密,加密规则如下:
        首先将数据倒序,然后将每位数字都加上5,再用和除以10的余数代替该数字,
        最后将第一位和最后一位数字交换。 请任意给定一个小于8位的整数,
        然后,把加密后的结果在控制台打印出来。
        * 分析:小于8位的整数:定义int类型变量,从键盘获取,Scanner
        *      将数据倒序,就要获取输入每一位的数,存到数组中
        *      将每位数字加5,取余10
        *      打印在控制台
        * */
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个8位数以下的数");
        int num = sc.nextInt(); //从键盘获取
        //存到数组中,先定义一个数组
        int [] arr = new int[8];//8位及以下,所以写8
        int index = 0;//不知道输入了几位数,所以自己定义一个索引
        //将从键盘获取的数据一位一位存到数组中
        while (num > 0){  //假设num12345,num = 1234,num = 123,num = 12,num = 1,num = 0,不符合循环条件
            arr[index] = num%10; //arr[0] = 5,arr[1] = 4,arr[2] = 3,arr[3] =2,arr[4] = 1
            num/=10;//num = 1234,num = 123,num = 12,num = 1,num = 0
            index++;//index = 1,index = 2,index = 3,index = 4,index =5,index为索引表示数组长度为5
        }
        //while循环中,不仅将数据写入到数组中,并且完成了倒序
        //将每位加5,取余10
        for (int i = 0; i < index; i++) {
            arr[i] += 5;
            arr[i] %= 10;
        }
        //打印
        for (int i = 0; i < index; i++) {  //index为索引,及数组长度
            System.out.print(arr[i]+" ");
        }

    }
}

Java中参数传递的问题
  -基本类型:形式参数的改变对实际参数没有影响,基本数据类型实参给方法形参传递的是数据值
  -引用类型:形式参数的改变直接影响实际参数,引用数据类型实参给方法形参传递的是地址值

//看程序写结果
class ArgsDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        System.out.println("a:"+a+",b:"+b); //a:10,b:20
        change(a,b);
        System.out.println("a:"+a+",b:"+b);  //a:10,b:20

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

    public static void change(int a,int b) { //a=10,b=20
        System.out.println("a:"+a+",b:"+b); //a:10,b:20
        a = b;  //a=20
        b = a + b; //b=40
        System.out.println("a:"+a+",b:"+b); //a:20,b:40
    }

    public static void change(int[] arr) { //arr={1,2,3,4,5};
        for(int x=0; x

Day6

面向对象
面向对象思想概述
  面向对象是基于面向过程的编程思想
面向对象思想特点
  -是一种更符合我们思想习惯的思想
  -可以将复杂的事情简单化
  -将我们从执行者变成了指挥者
在用面向对象思想体现的时候,给出一个三句话使用规则,让我们更符合面向对象思想
  -首先分析有那些类
  -接着分析每个类应该有什么
  -最后分析类与类的关系
面向对象开发
  就是不断的创建对象,使用对象,指挥对象做事情
面向对象设计
  其实就是在管理和维护对象之间的关系
面向对象特征
  -封装(encapsulation)
  -继承(inheritance)
  -多态(polymorphism)
如何表示一个现实世界事物呢:
  -属性 就是该事物的描述信息
  -行为 就是该事物能够做什么

类:是一组相关的属性和行为的集合
对象:是该类事物的具体体现

现实世界的事物
  属性 人的身高,体重等
  行为 人可以学习,吃饭等
Java中用class描述事物也是如此
  成员变量 就是事物的属性
  成员方法 就是事物的行为
定义类其实就是定义类的成员(成员变量和成员方法)
成员变量 和以前定义变量是一样的,只不过位置发生了改变,在类中,方法外
成员方法 和以前定义方法是一样的,只不过把static去掉

定义一个类
如何定义
按照事物到类的过程一步步分析

/*
    手机事物:
        属性:品牌,价格,颜色...
        行为:打电话,发短信,玩游戏...
        
    手机类:
        成员变量:品牌,价格,颜色
        成员方法:打电话,发短信,玩游戏
*/
class Phone {
    //品牌
    String brand;
    //价格
    int price;
    //颜色
    String color;
    
    //打电话的方法
    public void call(String name) {
        System.out.println("给"+name+"打电话");
    }
    
    //发短信的方法
    public void sendMessage() {
        System.out.println("群发短信");
    }
    
    //玩游戏的方法
    public void playGame() {
        System.out.println("玩游戏");
    }
}

类的调用
创建对象:
格式:类名 对象名 = new 类名();
使用:
  -对象名.成员变量
  -对象名.成员方法

/*
    手机类的测试
*/
class Phone {
    //品牌
    String brand;
    //价格
    int price;
    //颜色
    String color;
    
    //打电话的方法
    public void call(String name) {
        System.out.println("给"+name+"打电话");
    }
    
    //发短信的方法
    public void sendMessage() {
        System.out.println("群发短信");
    }
    
    //玩游戏的方法
    public void playGame() {
        System.out.println("玩游戏");
    }
}

class PhoneDemo {
    public static void main(String[] args) {
        //创建手机对象
        //类名 对象名 = new 类名();
        Phone p = new Phone();
        
        //直接输出成员变量值
        System.out.println(p.brand+"---"+p.price+"---"+p.color);
        
        //给成员变量赋值
        p.brand = "诺基亚";
        p.price = 100;
        p.color = "灰色";
        //再次输出
        System.out.println(p.brand+"---"+p.price+"---"+p.color);
        
        //调用方法
        p.call("张三");
        p.sendMessage();
        p.playGame();
    }
}

对象的内存图

对象的内存图

学生类

/*
    在一个java文件中写两个类:一个基本的类,一个测试类
    注意:文件名称和测试类名称一致
    
    如何使用呢?
        创建对象使用
        
    如何创建对象
        格式:类名 对象名 = new 类名();
        
    如何使用成员变量
        对象名.变量名
    如何使用成员方法
        对象名.方法名(...)
*/
//这是学生类
class Student {
    //姓名
    String name; //默认值null
    //年龄
    int age; //默认值0
    //地址
    String address; //默认值null
    
    //学习
    public void study() {
        System.out.println("学生爱学习");
    }
    
    //吃饭
    public void eat() {
        System.out.println("学习饿了,要吃饭");
    }
    
    //睡觉
    public void sleep() {
        System.out.println("学习累了,要睡觉");
    }
}

//这是学生测试类
class StudentDemo {
    public static void main(String[] args) {
        //类名 对象名 = new 类名();
        Student s = new Student();
        
        //输出成员变量值
        //System.out.println(s.name);
        //System.out.println(s.age);
        //System.out.println(s.address);
        //改进写法
        System.out.println(s.name+"---"+s.age+"---"+s.address);
        
        
        //给成员变量赋值
        s.name = "张三";
        s.age = 18;
        s.address = "北京";
        //赋值后的输出
        System.out.println(s.name+"---"+s.age+"---"+s.address);
        
        //调用方法
        s.study();
        s.eat();
        s.sleep();
    }
}

Day7

成员变量和局部变量的区别

在类中的位置不同
  -成员变量:在类中方法外
  -局部变量:在方法定义中或者方法声明上
在内存中的位置不同
  -成员变量:在堆内存
  -局部变量:在栈内存
生命周期不同
  -成员变量:随着对象的创建而存在,随着对象的消失而消失
  -局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
初始化值不同
  -成员变量:有默认初始化值
  -局部变量:没有默认初始化值,必须定义,赋值,然后才能使用

注意事项:
  局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则
匿名对象
  就是没有名字的对象
匿名对象的应用场景:
  调用方法,仅仅只调用一次的时候
注意:调用多次的时候,不适合
好处:匿名对象调用完毕就是垃圾。可以被垃圾回收器回收
匿名对象可以作为实际参数传递

private关键字
是一个权限修饰符
可以修饰成员变量和成员方法
被其修饰的成员只能在本类中被访问

封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

class Demo {
    //用private修饰
    private int num = 10;
    
    public void show() {
        System.out.println(num);
    }
    
    private void method() {
        System.out.println("method");
    }
    
    public void function() {
        method();
    }
}

class PrivateDemo {
    public static void main(String[] args) {
        Demo d = new Demo();
        //不能访问私有的成员变量
        //System.out.println(d.num);
        d.show();
        //不能访问私有的成员方法
        //d.method();
        d.function();
    }
}

对数据进行限制

class Student {
    //姓名
    String name;
    //年龄
    private int age;  //对年龄进行限制
    
    //写一个方法对数据进行限制
    public void setAge(int a) {
        if(a < 0 || a > 120) {
            System.out.println("你给的年龄有问题");
        }else {
            age = a;
        }
    }
    
    //show()方法,显示所有成员变量值
    public void show() {
        System.out.println("姓名:"+name);
        System.out.println("年龄:"+age);
    }
}

class StudentDemo {  //测试类
    public static void main(String[] args) {
        //创建学生对象
        Student s = new Student();
        s.show();
        System.out.println("--------------");
        
        //给成员变量赋值
        s.name = "张三";
        //s.age = 27;  //私有,不可访问
        s.setAge(27);
        s.show();
        System.out.println("--------------");
        
        //给age赋值
        //s.age = -27; //这个数据是不合理的
        //通过方法给值
        s.setAge(-27);
        s.show();
        System.out.println("--------------");
    }
}

封装private最常见的应用
  -把成员变量用private修饰
  -提供对应的getXxx()/setXxx()方法 set赋值,用来输入,get获取值,用来输出

class Student {
    //姓名
    private String name;
    //年龄
    private int age;
    
    //姓名获取值
    public String getName() {
        return name;
    }
    
    //姓名设置值
    public void setName(String n) {
        name = n;
    }
    
    //年龄获取值
    public int getAge() {
        return age;
    }
    
    //年龄赋值
    public void setAge(int a) {
        age = a;
    }
}

//测试类
class StudentTest {
    public static void main(String[] args) {
        //创建学生对象
        Student s = new Student();
        
        //使用成员变量
        //错误:被私有修饰了,外界不能直接访问了
        //System.out.println(s.name+"---"+s.age);
        System.out.println(s.getName()+"---"+s.getAge());
        
        //给成员变量赋值
        //s.name = "张三";
        //s.age = 27;
        //通过方法给赋值
        s.setName("张三");
        s.setAge(27);
        System.out.println(s.getName()+"---"+s.getAge());
    }
}

this关键字
this:是当前类的对象引用,简单的记,它就代表当前类的一个对象
注意:谁调用这个方法,在该方法内部的this就代表谁。
this的场景:
  解决局部变量隐藏成员变量

class Student {
    //姓名
    private String name;
    //年龄
    private int age;
    
    //姓名获取值
    public String getName() {
        return name;
    }
    
    //姓名设置值,起名字要做到见名知意
    public void setName(String name) { //name = "张三";
        //name = name; //变量的使用规则:就近原则
        //这里是类名,目前还没有说过类似的用法,所以这个是有问题的
        //这里的调用只能通过对象名
        //这个对象如果存在,它应该代表的是Student的一个对象
        //那么,谁能够代表当前类的对象呢? java就提供了一个关键字 this
        //Student.name = name;
        this.name = name;
    }
    
    //年龄获取值
    public int getAge() {
        return age;
    }
    
    //年龄赋值
    public void setAge(int age) {
        this.age = age;
    }
}

//测试类
class StudentTest {
    public static void main(String[] args) {
        //创建学生对象
        Student s = new Student();
        
        //给成员变量赋值
        s.setName("张三");
        s.setAge(27);
        //获取数据
        System.out.println(s.getName()+"---"+s.getAge());
    }
}
/*
    标准的代码改进版
    
    this:哪个对象调用那个方法,this就代表那个对象
*/
class Student {
    private String name;
    private int age;
    
    public String getName() {
        return name; //这里其实是隐含了this
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
}

class StudentTest2 {
    public static void main(String[] args) {
        //创建一个对象
        Student s1 = new Student();
        s1.setName("张三");
        s1.setAge(27);
        System.out.println(s1.getName()+"---"+s1.getAge());
        
        //创建第二个对象
        Student s2 = new Student();
        s2.setName("李四");
        s2.setAge(30);
        System.out.println(s2.getName()+"---"+s2.getAge());
    }
}

构造方法
构造方法作用概述
  给对象的数据进行初始化
构造方法格式
  方法名与类名相同
  没有返回值类型,连void都没有
  没有具体的返回值

class Student {
    private String name; //null
    private int age; //0
    
    public Student() {  //创建了一个构造方法
        System.out.println("这是构造方法");
    }
}

class ConstructDemo {
    public static void main(String[] args) {
        //创建对象
        Student s = new Student();
        System.out.println(s); //输出这是构造方法跟地址值,说明经过了上边的public Student
    }
}

构造方法注意事项
  如果你不提供构造方法,系统会给出默认构造方法
  如果你提供了构造方法,系统将不再提供
  构造方法也是可以重载的

构造方法赋值的形式

public class People {
    //姓名
    String name;
    //年龄
    int age;
    //住址
    String address;

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

    //有参
    public  People(String name,int age){
        this.name = name;
        this.age = age;
    }

    //三个参数
    public  People(String name,int age,String address){
        this.age = age;
        this.name = name;
        this.address = address;
    }

    //show打印所有信息
    public void show(){
        System.out.println("姓名:"+name+" 年龄:"+age+" 住址:"+address);
    }
}
class PeopleText{
    public static void main(String[] args) {
        //创建对象无参
        People p = new People();
        p.name = "张三";
        p.age = 18;
        p.address = "山东省";
        p.show();

        //两个参数的
        People p1 = new People("李四",15);
        p1.address = "北京省";
        p1.show();

        //三个参数的
        People p2 = new People("王五",15,"山东省");
        p2.show();
    }
}

给成员变量赋值有两种方式:
  -setXxx()
  -构造方法
成员方法
 根据返回值:
  -void类型
  -非void类型
 形式参数:
  -空参方法
  -非空参方法
四种方式的调用:

class Student {
    public String getString() {
        return "helloworld";
    }

    public void show() {
        System.out.println("show");
    }
    
    public void method(String name) {
        System.out.println(name);
    }
    
    public String function(String s1,String s2) {
        return s1+s2;
    }
}

class StudentDemo {
    public static void main(String[] args) {
        //创建对象
        Student s = new Student();
        
        //调用无参无返回值方法
        s.show();
        
        //调用无参有返回值方法
        String result = s.getString();
        System.out.println(result);
        
        //调用带参无返回值的方法
        s.method("张三");
        
        //调用带参带返回值的方法
        String result2 = s.function("hello","world");
        System.out.println(result2);
    }
}

类分为成员变量,构造方法,成员方法
 成员变量
 构造方法
  -无参构造方法
  -带参构造方法
 成员方法
  -getXxx()
  -setXxx()
类的标准写法

/*
    学生类:
        成员变量:
            name,age
        构造方法:
            无参,带两个参
        成员方法:
            getXxx()/setXxx()
            show():输出该类的所有成员变量值
            
    给成员变量赋值:
        A:setXxx()方法
        B:构造方法
        
    输出成员变量值的方式:
        A:通过getXxx()分别获取然后拼接
        B:通过调用show()方法搞定
*/
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 void show() {
        System.out.println(name+"---"+age);
    }
}

//测试类
class StudentTest {
    public static void main(String[] args) {
        //方式1给成员变量赋值
        //无参构造+setXxx()
        Student s1 = new Student();
        s1.setName("张三");
        s1.setAge(27);
        //输出值
        System.out.println(s1.getName()+"---"+s1.getAge());
        s1.show();
        System.out.println("----------------------------");
        
        //方式2给成员变量赋值
        Student s2 = new Student("李四",30);
        System.out.println(s2.getName()+"---"+s2.getAge());
        s2.show();
    }
}

注意:
 -给成员变量赋值有两种方式,可以只写一种,推荐使用setXxx()方法,单个输入更灵活
 -如果不单独获取数据,可以不写getXxx()方法

类的初始化过程
Student s = new Student();在内存中做了哪些事情
 -加载Student.class文件进内存
 -在栈内存为s开辟空间
 -在堆内存为学生对象开辟空间
 -对学生对象的成员变量进行默认初始化
 -对学生对象的成员变量进行显示初始化
 -通过构造方法对学生对象的成员变量赋值
 -学生对象初始化完毕,把对象地址赋值给s变量

static关键字
 可以修饰成员变量和成员方法
static关键字特点
  -随着类的加载而加载
  -优先于对象存在
  -被类的所有对象共享(这也是我们判断是否使用静态关键字的条件)
  -可以通过类名调用
可以通过类名和对象名调用

class Student {
    //非静态变量
    int num = 10;
    
    //静态变量
    static int num2 = 20;
}

class StudentDemo {
    public static void main(String[] args) {
        Student s = new Student();
        System.out.println(s.num);
        
        System.out.println(Student.num2);  //可以通过类名调用
        System.out.println(s.num2); //可以通过对象调用
    }
}
/*
    定义一个人类
    
    姓名和年龄都是变化的,因为每个人的姓名和年龄是不同的。
    但是,我们想到的都是中国人,他们的国籍是一样的。
    一样的国籍,我每次创建对象,在堆内存都要开辟这样的空间,很浪费
        针对多个对象有共同的这样的成员变量值的时候,
        Java就提高了一个关键字来修饰:static。
*/
class Person {
    //姓名
    String name;
    //年龄
    int age;
    //国籍
    static String country;  //静态修饰
    
    public Person(){}
    
    public Person(String name,int age) {
        this.name = name;
        this.age = age;
    }
    
    public Person(String name,int age,String country) {
        this.name = name;
        this.age = age;
        this.country = country;
    }
    
    public void show() {
        System.out.println("姓名:"+name+",年龄:"+age+",国籍:"+country);
    }
}

class PersonDemo {
    public static void main(String[] args) {
        //创建对象1
        Person p1 = new Person("邓丽君",16,"中国");
        p1.show();//输出姓名:邓丽君,年龄16,国籍中国
        
        //创建对象2
        Person p2 = new Person("杨幂",22);  //因为country是静态static修饰的,相当于默认值,所以这个不赋值也是中国
        p2.show();//输出姓名:杨幂,年龄22,国籍中国
        
        //创建对象3
        Person p3 = new Person("凤姐",20);
        p3.show(); //同上
        
        p3.country = "美国";
        p3.show();//输出姓名:凤姐,年龄20,国籍美国
        
        p1.show();//输出姓名:邓丽君,年龄16,国籍美国
        p2.show();//输出姓名:杨幂,年龄22,国籍美国
            //p1  p2的国际为什么改变,因为用的同一个静态修饰即默认值,在内存中用的同一块地址,所以会改变
    }
}

static关键字注意事项
  -在静态方法中是没有this关键字的
  -静态方法只能访问静态的成员变量和静态的成员方法

/*static关键字注意事项
    在静态方法中是没有this关键字的
    如何理解呢?
        静态是随着类的加载而加载,this是随着对象的创建而存在。
        静态比对象先存在。
    静态方法只能访问静态的成员变量和静态的成员方法
        静态方法:
            成员变量:只能访问静态变量
            成员方法:只能访问静态成员方法
        非静态方法:
            成员变量:可以是静态的,也可以是非静态的
            成员方法:可是是静态的成员方法,也可以是非静态的成员方法。
    简单记:
        静态只能访问静态。
*/
class Teacher {
    public int num = 10;
    public static int num2 = 20;
    
    public void show() {
        System.out.println(num); //隐含的告诉你访问的是成员变量
        System.out.println(this.num); //明确的告诉你访问的是成员变量
        System.out.println(num2);
        
        //function();
        //function2();
    }
    
    public static void method() {
        //无法从静态上下文中引用非静态 变量 num
        //System.out.println(num);
        System.out.println(num2);
        
        //无法从静态上下文中引用非静态 方法 function()
        //function();
        function2();
    }
    
    public void function() {
    
    }
    
    public static void function2() {
    
    }
}

class TeacherDemo {
    public static void main(String[] args) {
        //创建对象
        Teacher t = new Teacher();
        t.show();
        System.out.println("------------");
        t.method();
    }
}

静态变量和成员变量的区别
 所属不同
  -静态变量属于类,所以也称为为类变量
  -成员变量属于对象,所以也称为实例变量(对象变量)
 内存中位置不同
  -静态变量存储于方法区的静态区
  -成员变量存储于堆内存
 内存出现时间不同
  -静态变量随着类的加载而加载,随着类的消失而消失
  -成员变量随着对象的创建而存在,随着对象的消失而消失
 调用不同
  -静态变量可以通过类名调用,也可以通过对象调用
  -成员变量只能通过对象名调用
main方法详解
main方法的格式讲解:
public static void main(String[] args) {...}
  public:公共的,访问权限是最大的。由于main方法是被jvm调用,所以权限要够大
  static:静态的,不需要创建对象,通过类名就可以,方便jvm的调用
  void:因为我们曾经说过,方法的返回值是返回给调用者,而main方法是被jvm调用,你返回内容给jvm没有意义
  main:是一个常见的方法入口。我见过的语言都是以main作为入口
  String[] args:这是一个字符串数组,这个东西早期是为了接收键盘录入的数据的
  格式是:java MainDemo hello world java

Day8

制作一个代码说明书

/*
    我想要对数组进行操作
    
    如何制作一个说明书呢
        写一个工具类
        对这个类加入文档注释
            怎么加
            加些什么东西
        用工具解析文档注释
            javadoc工具
        格式
            javadoc -d 目录 -author -version ArrayTool.java
            
            目录:就可以写一个文件夹的路径
            
    制作帮助文档出错:
        找不到可以文档化的公共或受保护的类:告诉我们类的权限不够
*/
class ArrayDemo {
    public static void main(String[] args) {
        //定义数组
        int[] arr = {28,55,37,46,19};
        
        //遍历
        ArrayTool.printArray(arr);

        //获取最值
        int max = ArrayTool.getMax(arr);
        System.out.println("max:"+max);
        
        //获取55的索引值
        int index = ArrayTool.getIndex(arr,55);
        System.out.println("index:"+index);
    }
}

/**
* 这是针对数组进行操作的工具类
* @author 张三
* @version V1.0
*/
public class ArrayTool {
    
    //把构造方法私有,外界就不能在创建对象了
    /**
    * 这是私有构造
    */
    private ArrayTool(){}

    /**
    * 这是遍历数组的方法,遍历后的格式是:[元素1, 元素2, 元素3, ...]
    * @param arr 这是要被遍历的数组
    */
    public static void printArray(int[] arr) {
        System.out.print("[");
        for(int x=0; x max) {
                max = arr[x];
            }
        }
        
        return max;
    }
    
    /**
    * 获取指定元素在数组中第一次出现的索引,如果元素不存在,就返回-1
    * @param arr 被查找的数组 
    * @param value 要查找的元素
    * @return 返回元素在数组中的索引,如果不存在,返回-1
    */
    public static int getIndex(int[] arr,int value) {
        int index = -1;
        
        for(int x=0; x

上列代码生成的说明书



如何使用JDK的帮助文档
1:打开帮助文档
2:点击显示,找到索引,看到输入框
3:知道你要找谁?以Scanner举例
4:在输入框里面输入Scanner,然后回车
5:看包
  java.lang包下的类不需要导入,其他的全部需要导入。
  要导入:java.util.Scanner
6:再简单的看看类的解释和说明,别忘了看看该类的版本
7:看类的结构
  成员变量 字段摘要
  构造方法 构造方法摘要
  成员方法 方法摘要
8:学习构造方法
  有构造方法 就创建对象
  没有构造方法 成员可能都是静态的
9:看成员方法
 左边
  是否静态:如果静态,可以通过类名调用
  返回值类型:人家返回什么,你就用什么接收
 右边
  看方法名:方法名称不要写错
  参数列表:人家要什么,你就给什么;人家要几个,你就给几个

Random方法
第一步先导包:import java.util.Random;
第二步创建对象:Random r = new Random(); //r 和 num 为变量名,可以改
第三步使用: int num = r.nextInt(20)+1; //20表示从0开始生成20个数据,+1表示从1-20

猜数字小游戏

import java.util.Random;
import java.util.Scanner;

public class CaiNumber {
    //猜数字范围(1-20)
    /*
    * 分析:系统生成一个随机数
    *      用户进行输入一个数
    *      进行比较
    *          大了
    *          小了
    *          猜中了
    *       不确定多少次猜中,用while,猜中就break;
    * */
    public static void main(String[] args) {
        Random r = new Random();
        System.out.println("系统生成随机数");
        int goodNum = r.nextInt(20)+1;

        //System.out.println(goodNum);

        //定义死循环进行猜数字
        Scanner sc = new Scanner(System.in);
        while(true) {
            System.out.println("用户输入猜测的数");
            int num = sc.nextInt();
            if (num < goodNum){
                System.out.println("猜小了,请继续");
            }else if (num > goodNum){
                System.out.println("猜大了,请继续");
            }else {
                System.out.println("猜中了");
                break;
            }
        }
    }
}

代码块
在Java中,使用{}括起来的代码被称为代码块,根据其位置和声明的不同,可以分为
  -局部代码块
  -构造代码块
  -静态代码块
  -同步代码块(多线程讲解)
局部代码块
  在方法中出现;限定变量生命周期,及早释放,提高内存利用率
构造代码块
  在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行
静态代码块 在类中方法外出现,加了static修饰
  在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且值执行一次
静态代码块,构造代码块,构造方法的顺序问题
  静态代码块 > 构造代码块 > 构造方法
静态代码块:只执行一次
构造代码块:每次调用构造方法都执行

/*
    写程序的执行结果。
    输出结果:
      main函数静态方法    
      我是main方法
      Student 静态代码块
      Student 构造代码块
      Student 构造方法
      Student 构造代码块
      Student 构造方法
先调用main方法中的静态代码块,在调用main方法,创建对象s1,执行Student类中的方法,先执行静态,在执行构造代码块,最后执行构造方法,在创建对象s2,执行Student类中的方法,静态只执行一次,所以只执行构造代码块和构造方法
*/
class Student {
    static {
        System.out.println("Student 静态代码块");
    }
    
    {
        System.out.println("Student 构造代码块");
    }
    
    public Student() {
        System.out.println("Student 构造方法");
    }
}

class StudentDemo {
    static {
        System.out.println("main函数静态方法");
    }
    
    public static void main(String[] args) {
        System.out.println("我是main方法");
        
        Student s1 = new Student();  //创建对象
        Student s2 = new Student();
    }
}

继承
继承概述:
  把多个类中相同的内容给提取出来定义到一个类中。
如何实现继承呢?
  Java提供了关键字:extends
格式:
  class 子类名 extends 父类名 {}
好处:
  -提高了代码的复用性
  -提高了代码的维护性
  -让类与类之间产生了关系,是多态的前提
类与类产生了关系,其实也是继承的一个弊端:
  类的耦合性增强了。
开发的原则:低耦合,高内聚。
  耦合:类与类的关系
  内聚:就是自己完成某件事情的能力

//使用继承前
class Student {
    public void eat() {
        System.out.println("吃饭");
    }
    
    public void sleep() {
        System.out.println("睡觉");
    }
}

class Teacher {
    public void eat() {
        System.out.println("吃饭");
    }
    
    public void sleep() {
        System.out.println("睡觉");
    }
}


//使用继承后
class Person {
    public void eat() {
        System.out.println("吃饭");
    }
    
    public void sleep() {
        System.out.println("睡觉");
    }
}

class Student extends Person {}  //继承格式

class Teacher extends Person {}

class ExtendsDemo {
    public static void main(String[] args) {
        Student s = new Student();
        s.eat();
        s.sleep();
        System.out.println("-------------");
        
        Teacher t = new Teacher();
        t.eat();
        t.sleep();
    }
}

Java继承的特点
  -Java只支持单继承,不支持多继承
  -Java支持多层继承(继承体系)

class Father {}
class Mother {}
class Son exnteds Father {} //正确的
class Son extends Father,Mother {} // 错误的,不可以多继承
*/

class GrandFather {
    public void show() {
        System.out.println("我是爷爷");
    }
}

class Father extends GrandFather {  //老子继承爷爷的
    public void method(){
        System.out.println("我是老子");
    }
}

class Son extends Father {}  //儿子继承老子的,构成多层继承

class ExtendsDemo2 {
    public static void main(String[] args) {
        Son s = new Son();
        s.method(); //使用父亲的
        s.show(); //使用爷爷的
    }
}

Java继承中的成员关系
成员变量
 子类的成员变量名称和父类中的成员变量名称不一样,通过名称访问
 子类的成员变量名称和父类中的成员变量名称一样
  子类的方法访问变量的查找顺序:
   -在子类方法的局部范围找,有就使用
   -在子类的成员范围找,有就使用
   -在父类的成员范围找,有就使用
   -找不到,就报错
构造方法
 子类的构造方法默认会去访问父类的无参构造方法
  是为了子类访问父类数据的初始化
父类中如果没有无参构造方法,怎么办
  -子类通过super去明确调用带参构造
  -子类通过this调用本身的其他构造,但是一定会有一个去访问了父类的构造
  -让父类提供无参构造
成员方法
  子类的成员方法和父类中的成员方法名称不一样,通过名称
  子类的成员方法和父类中的成员方法名称一样,
   通过子类对象访问一个方法的查找顺序:
    -在子类中找,有就使用
    -在父类中找,有就使用
    -找不到,就报错

继承的注意事项
  -子类只能继承父类所有非私有的成员(成员方法和成员变量)
  -子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法
  -不要为了部分功能而去继承

什么时候考虑用继承
继承其实体现的是一种关系:"is a"。
  Person  //人
  Student //学生
  Teacher //老师
老师是人,学生也是人,就考虑继承

水果
  苹果 //是水果的一种
  香蕉 //是水果的一种
采用假设法
  如果有两个类A,B,只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承

类的组成
  -成员变量:
  -构造方法:
  -成员方法:
在子类方法中访问一个变量的查找顺序:
  -在子类方法的局部范围找,有就使用
  -在子类的成员范围找,有就使用
  -在父类的成员范围找,有就使用
  -如果还找不到,就报错
super关键字
  代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)
this 代表本类对应的引用
用法:
 调用成员变量
  this.成员变量 调用本类的成员变量
  super.成员变量 调用父类的成员变量
 调用构造方法
  this(...) 调用本类的构造方法
  super(...) 调用父类的构造方法
 调用成员方法
  this.成员方法 调用本类的成员方法
  super.成员方法 调用父类的成员方法

继承中构造方法的关系
  子类中所有的构造方法默认都会访问父类中空参数的构造方法
  因为子类会继承父类中的数据,可能还会使用父类的数据,所以,子类初始化之前,一定要先完成父类数据的初始化

注意:子类每一个构造方法的第一条语句默认都是:super();

class Father {
    int age;

    public Father() {
        System.out.println("Father的无参构造方法");
    }
    
    public Father(String name) {
        System.out.println("Father的带参构造方法");
    }
}

class Son extends Father {
    public Son() {
        //super();
        System.out.println("Son的无参构造方法");
    }
    
    public Son(String name) {
        //super();
        System.out.println("Son的带参构造方法");
    }
}   

class ExtendsDemo6 {
    public static void main(String[] args) {
        //创建对象
        Son s = new Son();
        System.out.println("------------");
        Son s2 = new Son("张三");  //不管子类是有参还是无参,都走父类的无参构造
    }
}

//运行结果
Father的无参构造方法
Son的无参构造方法
------------
Father的无参构造方法
Son的带参构造方法

如果父类没有无参构造方法,那么子类的构造方法会报错

如何解决
  -在父类中加一个无参构造方法
  -通过使用super关键字去显示的调用父类的带参构造方法
  -子类通过this去调用本类的其他构造方法
子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化

注意事项:
  this(...)或者super(...)必须出现在第一条语句上
如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化,所以必须放在第一条语句上


class Father {
    /*
    public Father() {
        System.out.println("Father的无参构造方法");
    }
    */
    
    public Father(String name) {
        System.out.println("Father的带参构造方法");
    }
}

class Son extends Father {
    public Son() {
        super("随便给");
        System.out.println("Son的无参构造方法");
        //super("随便给");
    }
    
    public Son(String name) {
        //super("随便给");
        this();
        System.out.println("Son的带参构造方法");
    }
}

class ExtendsDemo7 {
    public static void main(String[] args) {
        Son s = new Son();  
        System.out.println("----------------");
        Son ss = new Son("张三");
    }
}
//结果
Father的带参构造方法
Son的无参构造方法
----------------
Father的带参构造方法
Son的无参构造方法
Son的带参构造方法

方法重写
 方法重写:子类中出现了和父类中方法声明一模一样的方法
 方法重载:本类中出现的方法名一样,参数列表不同的方法,与返回值无关
 子类对象调用方法的时候:先找子类本身,再找父类
方法重写的应用:
  当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容

/*
  手机都有通话功能
  新手机通话完成后会显示通话时间
*/
class Phone {
    public void call(String name) {
        System.out.println("给"+name+"打电话");
    }
}

class NewPhone extends Phone {
    public void call(String name) {
        //System.out.println("给"+name+"打电话");
        super.call(name);  //调用父类中的方法
        System.out.println("通话时长");
    }
}

class ExtendsDemo9 {
    public static void main(String[] args) {
        NewPhone np = new NewPhone();
        np.call("张三");  //结果:给张三打电话,通话时长
    }
}

方法重写的注意事项
 -父类中私有方法不能被重写
  因为父类私有方法子类根本就无法继承
 -子类重写父类方法时,访问权限不能更低
  最好就一致
 -父类静态方法,子类也必须通过静态方法进行重写
子类重写父类方法的时候,最好声明一模一样

练习
1:方法重写和方法重载的区别?方法重载能改变返回值类型吗?
方法重写:
  在子类中,出现和父类中一模一样的方法声明的现象。
方法重载:
  同一个类中,出现的方法名相同,参数列表不同的现象。
方法重载能改变返回值类型,因为它和返回值类型无关。
Override:方法重写
Overload:方法重载

2:this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。

this:代表当前类的对象引用
super:代表父类存储空间的标识。(可以理解为父类的引用,通过这个东西可以访问父类的成员)

场景:
 成员变量:
  this.成员变量
  super.成员变量
 构造方法:
  this(...)
  super(...)
 成员方法:
  this.成员方法
  super.成员方法
继承版猫狗案例

/*
* 猫狗案例
* 分析:
* 猫类:
*   成员变量:
*       姓名,年龄,颜色
*   构造方法:
*       有参跟无参
*   成员方法:
*       吃饭,睡觉,捉老鼠(猫特有)
* 狗类:
*   成员变量:
*       姓名,年龄,颜色
*   构造方法:
*       有参跟无参
*   成员方法:
*       吃饭,睡觉,看门(狗特有)
*
* 把公共部门定义成一个类
* 动物类:
* 成员变量:
*       姓名,年龄,颜色
*   构造方法:
*       有参跟无参
*   成员方法:
*       吃饭,睡觉
* */
class Animal {
   //姓名
   private String name;
   // 年龄
   private int age;
   // 颜色
   private String color;

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

   public Animal(String name, int age, String color) {  //有参
       this.name = name;
       this.age = age;
       this.color = color;
   }

   //成员方法:get,sat,吃饭,睡觉
   //姓名
   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 String getColor() {
       return color;
   }

   public void setColor(String color) {
       this.color = color;
   }

   //吃饭
   public void eat() {
       System.out.println(name + "吃饭");
   }

   //睡觉
   public void sleep() {
       System.out.println(name + "睡觉");
   }
}

   //猫类
class Cat extends Animal{
       //无参构造
       public Cat(){}

       //有参构造
       public Cat(String name,int age,String color){
           super(name, age, color);
       }
       public void playGame(){
           System.out.println(super.getName()+"捉老鼠");  //调用父类的成员方法,输出姓名
       }
}

   //狗类
class Dog extends Animal{
       //无参构造
       public Dog(){}

       //有参构造
       public Dog(String name,int age,String color){
           super(name, age, color);
      }

       public void lookDoor(){
           System.out.println(super.getName()+"看门");
       }
}
class Text{  //测试类
   public static void main(String[] args) {
       //猫无参
       Cat cat = new Cat();
       cat.setName("小花");
       cat.setColor("花色");
       cat.setAge(18);
       cat.eat();
       cat.playGame();
       System.out.println(cat.getName()+cat.getAge()+cat.getColor());

       System.out.println("----------");
       //猫有参
       Cat cat1 = new Cat("甜甜",15,"蓝色");
       cat1.playGame();
       cat.sleep();
       System.out.println(cat1.getName()+cat1.getAge()+cat1.getColor());

       System.out.println("----------");
       //狗无参
       Dog dog = new Dog();
       dog.setName("小黑");
       dog.setAge(17);
       dog.setColor("黑色");
       dog.eat();
       dog.lookDoor();
       System.out.println(dog.getName()+dog.getAge()+dog.getColor());

       System.out.println("----------");
       //狗类有参
       Dog dog1 = new Dog("小白",13,"白色");
       dog1.eat();
       dog1.lookDoor();
       System.out.println(dog1.getName()+dog1.getAge()+dog1.getColor());
   }
}
/*
结果:
小花吃饭
小花捉老鼠
小花18花色
----------
甜甜捉老鼠
小花睡觉
甜甜15蓝色
----------
小黑吃饭
小黑看门
小黑17黑色
----------
小白吃饭
小白看门
小白13白色
*/

Day9

final关键字
继承的代码体现
由于继承中方法有一个现象:方法重写
所以,父类的功能,就会被子类给覆盖掉,有些时候,我们不想让子类去覆盖掉父类的功能,只能让他使用,这个时候,针对这种情况,Java就提供了一个关键字:final
final:最终的意思,常见的是它可以修饰类,方法,变量

class Fu {
    //public void show() {  将show改为用final修饰
      public final void show {
        System.out.println("这里是绝密资源,任何人都不能修改");
    }
}

class Zi extends Fu {
      //Zi中的show就无法覆盖Fu中的show
    public void show() {
        System.out.println("这是一堆垃圾");
    }
}

class ZiDemo {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show();
    }
}

final可以修饰类,方法,变量
特点:
final修饰类,该类不可以被继承
final修饰方法,该方法不能被重写
final修饰变量,该变量不能被重新赋值

final也可以修饰局部变量
  基本数据类型的值不可以改变
  引用数据类型的地址值不可以改变,但是该对象堆内存的值可以改变

final修饰变量初始化时机
  被final修饰的变量只能被赋值一次
  在构造方法完成前(非静态的常量)

多态
是指同一个事物(对象),在不同时刻表现出来的不同的状态、
例:猫是猫,猫也是动物
多态的前提:
 要有继承关系
 要有方法重写
 要有父类引用指向子类对象
  父类 fu = new 子类();
用代码体现一下多态

class Fu{
  public void show(){
    System,out.println("这是父类的show");
  }
}
class Zi extends Fu{  //要有继承关系
  public void show(){
    System,out.println("这是子类的show");  //要有方法重写
  }
}
class DuiTai{
  public static void main(String[] args){
    Fu fu = new Zi();  //要有父类引用指向子类对象
  }
}

多态中的成员访问特点
 成员变量
  编译看左边,运行看左边
 构造方法
  创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化
 成员方法
  编译看左边,运行看右边
 静态方法
  编译看左边,运行看左边
  (静态和类相关,算不上重写,所以,访问还是左边的)
由于成员方法存在方法重写,所以它运行看右边

class Fu {
    public int num = 100;

    public void show() {
        System.out.println("show Fu");
    }
    
    public static void function() {  //静态
        System.out.println("function Fu");
    }
}

class Zi extends Fu {
    public int num = 1000;
    public int num2 = 200;

    public void show() {
        System.out.println("show Zi");
    }
    
    public void method() {
        System.out.println("method zi");
    }
    
    public static void function() {  //静态
        System.out.println("function Zi");
    }
}

class DuoTaiDemo {
    public static void main(String[] args) {
        //要有父类引用指向子类对象。
        //父 f =  new 子();
        Fu f = new Zi();
        System.out.println(f.num);  //输出100,成员变量运行看左边
        //找不到符号,成员变量编译看左边
        //System.out.println(f.num2);
        
        f.show();  //输出showZi,成员方法运行看右边,因为有方法重写
        //找不到符号,成员方法编译看左边,父类中没有,所以找不到
        //f.method();
        f.function();  //输出funcyion  Fu,静态方法编译看左边,输出看左边
    }
}

多态的好处
提高了代码的维护性(由继承保证)
提高了代码的扩展性(由多态保证)

class Animal {
    public void eat(){
        System.out.println("eat");
    }
    
    public void sleep(){
        System.out.println("sleep");
    }
}

class Dog extends Animal {
    public void eat(){
        System.out.println("狗吃肉");
    }
    
    public void sleep(){
        System.out.println("狗站着睡觉");
    }
}

class Cat extends Animal {
    public void eat() {
        System.out.println("猫吃鱼");
    }
    
    public void sleep() {
        System.out.println("猫趴着睡觉");
    }
}

class Pig extends Animal {
    public void eat() {
        System.out.println("猪吃白菜");
    }
    
    public void sleep() {
        System.out.println("猪侧着睡");
    }
}

//针对动物操作的工具类
class AnimalTool {   
    private AnimalTool(){}

    /*
    //调用猫的功能
    public static void useCat(Cat c) {
        c.eat();
        c.sleep();
    }
    
    //调用狗的功能
    public static void useDog(Dog d) {
        d.eat();
        d.sleep();
    }
    
    //调用猪的功能
    public static void usePig(Pig p) {
        p.eat();
        p.sleep();
    }
    */
    public static void useAnimal(Animal a) {  //因为每添加一个动物类就要改工具类,所以直接改成动物类
        a.eat();
        a.sleep();
    }
    
}

class DuoTaiDemo2 {
    public static void main(String[] args) {
        //我喜欢猫,就养了一只
        Cat c = new Cat();
        c.eat();
        c.sleep();
        
        //我很喜欢猫,所以,又养了一只
        Cat c2 = new Cat();
        c2.eat();
        c2.sleep();
        
        //我特别喜欢猫,又养了一只
        Cat c3 = new Cat();
        c3.eat();
        c3.sleep();
        //...
        System.out.println("--------------");
        //问题来了,我养了很多只猫,每次创建对象是可以接受的
        //但是呢?调用方法,你不觉得很相似吗?仅仅是对象名不一样。
        //我们准备用方法改进
        //调用方式改进版本
        //useCat(c);
        //useCat(c2);
        //useCat(c3);
        
        //AnimalTool.useCat(c);
        //AnimalTool.useCat(c2);
        //AnimalTool.useCat(c3);
        
        AnimalTool.useAnimal(c);
        AnimalTool.useAnimal(c2);
        AnimalTool.useAnimal(c3);
        System.out.println("--------------");
        
        //我喜欢狗
        Dog d = new Dog();
        Dog d2 = new Dog();
        Dog d3 = new Dog();
        //AnimalTool.useDog(d);
        //AnimalTool.useDog(d2);
        //AnimalTool.useDog(d3);
        AnimalTool.useAnimal(d);
        AnimalTool.useAnimal(d2);
        AnimalTool.useAnimal(d3);
        System.out.println("--------------");
        
        //我喜欢宠物猪
        //定义一个猪类,它要继承自动物,提供两个方法,并且还得在工具类中添加该类方法调用
        Pig p = new Pig();
        Pig p2 = new Pig();
        Pig p3 = new Pig();
        //AnimalTool.usePig(p);
        //AnimalTool.usePig(p2);
        //AnimalTool.usePig(p3);
        AnimalTool.useAnimal(p);
        AnimalTool.useAnimal(p2);
        AnimalTool.useAnimal(p3);
        System.out.println("--------------");
        
        //我喜欢宠物狼,老虎,豹子...
        //定义对应的类,继承自动物,提供对应的方法重写,并在工具类添加方法调用
        //前面几个必须写,我是没有意见的
        //但是,工具类每次都改,麻烦不
        //我就想,你能不能不改了
        //太简单:把所有的动物都写上。问题是名字是什么呢?到底哪些需要被加入呢?
        //改用另一种解决方案。
        
    }
    
    /*
    //调用猫的功能
    public static void useCat(Cat c) {
        c.eat();
        c.sleep();
    }
    
    //调用狗的功能
    public static void useDog(Dog d) {
        d.eat();
        d.sleep();
    }
    */
}

多态的弊端
不能使用子类特有的功能

class Fu{
  public void show(){
    System.out.println(show 父类);
  }
}
class Zi extends Fu{
  public void show(){
    System.out.println(show 子类);
  }
  public void eat(){
    System.out.println("吃饭");
  }
}
class DuoTai{
  public static void main(String[] args){
    Fu fu = new Zi();
    fu.show();  //可以执行
    fu.eat();  //不可以执行,父类不能访问子类特有的功能
   }
}

如何解决多态的弊端:
  -可以新建一个子类对象调用子类特有的方法
  -向下转型
   Zi z = (Zi) f; //要求该f必须能转化成Zi的

对象间的转型问题
向上转型:
  Fu f = new Zi();
向下转型:
  Zi z = (Zi)f; //要求该f必须是能够转换为Zi的

错误提示:ClassCastException:类型转换异常,一般在多态的向下转型中容易出现

多态版猫狗案例

class DongWu{  //动物类
    //吃饭
    public void eat(){
        System.out.println("吃饭");
    }

    //睡觉
    public void sleep(){
        System.out.println("睡觉");
    }
}
class Mao extends DongWu{  //定义猫类继承动物类
    //吃饭
    public void eat(){
        System.out.println("猫吃鱼");
    }

    //睡觉
    public void sleep(){
        System.out.println("猫趴着睡觉");
    }

    //猫玩游戏
    public void playGame(){
        System.out.println("猫玩捉迷藏");
    }
}
class Gou extends DongWu{  //定义狗类继承动物类
    //吃饭
    public void eat(){
        System.out.println("狗吃肉");
    }

    //睡觉
    public void sleep(){
        System.out.println("狗站着睡觉");
    }

    //看门
    public void lookDoor(){
        System.out.println("狗看门");
    }
}
public class DuoTaiTest {
    /*
    * 用多态实现猫狗案例
    * 分析:
    *   多态要有继承
    *   多态要有父类指向子类对象
    *   要有方法重写
    * */
    public static void main(String[] args) {
        //将动物定义为狗
        DongWu dw = new Gou();
        dw.eat();
        dw.sleep();
        //无法执行dw.lookDoor
        //还原为狗
        Gou g = (Gou)dw;
        g.lookDoor();
        System.out.println("--------");
        dw = new Mao();
        dw.sleep();
        dw.eat();
        Mao m = (Mao)dw;
        m.playGame();

    }

}

练习

/*
    看程序写结果:先判断有没有问题,如果没有,写出结果
*/
class Fu {
    public void show() {
        System.out.println("fu show");
    }
}

class Zi extends Fu {
    public void show() {
        System.out.println("zi show");
    }

    public void method() {
        System.out.println("zi method");
    }
}

class DuoTaiTest3 {
    public static void main(String[] args) {
        Fu f = new Zi();
        //找不到符号
        //f.method();  //有问题,多态中成员方法编译看左边,父类中没有method方法,所以报错,找不到符号
        f.show();  //可以运行,编译看左边,父类中有show方法,运行看右边,输出右边的子类show,子类重写父类
    }
}

多态的成员访问特点:
  方法:编译看左边,运行看右边
继承的时候:
  子类中有和父类中一样的方法,叫重写
  子类中没有父亲中出现过的方法,方法就被继承过来了

/*
    看程序写结果:先判断有没有问题,如果没有,写出结果

*/
class A {
    public void show() {
        show2();
    }
    public void show2() {
        System.out.println("我");
    }
}
class B extends A {
    /*
    public void show() {  //被继承,相当于有
        show2();
    }
    */

    public void show2() {
        System.out.println("爱");
    }
}
class C extends B {
    public void show() {
        super.show();
    }
    public void show2() {
        System.out.println("你");
    }
}
public class DuoTaiTest4 {
    public static void main(String[] args) {
        A a = new B();
        a.show();  //打印爱
        
        B b = new C();
        b.show();  //打印你
    }
}

抽象类
抽象类得声明格式:用abstract修饰
例:abstract class Person

抽象类的概述:
  动物不应该定义为具体的东西,而且动物中的吃,睡等也不应该是具体的,我们把一个不是具体的功能称为抽象的功能,而一个类中如果有抽象的功能,该类必须得是抽象类
抽象类的特点:
  抽象类和抽象方法必须用abstract关键字修饰
  抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类
  抽象类不能实例化,因为他不是具体的
  抽象类有构造方法,用于子类访问父类数据的初始化
抽象的子类
  抽象类,可以不重写父类的抽象方法
  具体类,必须重写父类所有的抽象方法
抽象类的实例化其实是靠具体的子类实现的。是多态的方式
  Animal a = new Cat();


//abstract class Animal //抽象类的声明格式
abstract class Animal {
    //抽象方法
    //public abstract void eat(){} //空方法体,这个会报错。抽象方法不能有主体
    public abstract void eat();  //空方法体
    
    public Animal(){}
}

//子类是抽象类
abstract class Dog extends Animal {}

//子类是具体类
class Cat extends Animal {
    public void eat() {
        System.out.println("猫吃鱼"); //就需要重写父类的所有抽象方法
    }
}

class AbstractDemo {
    public static void main(String[] args) {
        //创建对象
        //Animal是抽象的; 无法实例化
        //Animal a = new Animal();
        //可以通过多态的方式实现抽象类的实例化
        Animal a = new Cat();
        a.eat();
    }
}

抽象类的成员特点:
  成员变量:既可以是变量,也可以是常量
  构造方法:有,用于子类访问父类数据的初始化
  成员方法:既可以是抽象的,也可以是非抽象的
抽象类的成员方法特性:
  抽象方法 强制要求子类做的事情
  非抽象方法 子类继承的事情,提高代码复用性

抽象类猫狗案例

猫狗案例
    具体事物:猫,狗
    共性:姓名,年龄,吃饭

分析:从具体到抽象
    猫:
        成员变量:姓名,年龄
        构造方法:无参,带参
        成员方法:吃饭(猫吃鱼)
        
    狗:
        成员变量:姓名,年龄
        构造方法:无参,带参
        成员方法:吃饭(狗吃肉)
        
    因为有共性的内容,所以就提取了一个父类。动物。
    但是又由于吃饭的内容不一样,所以吃饭的方法是抽象的,
    而方法是抽象的类,类就必须定义为抽象类。
    
    抽象动物类:
        成员变量:姓名,年龄
        构造方法:无参,带参
        成员方法:吃饭();

实现:从抽象到具体
    动物类:
        成员变量:姓名,年龄
        构造方法:无参,带参
        成员方法:吃饭();
        
    狗类:
        继承自动物类
        重写吃饭();
        
    猫类:
        继承自动物类
        重写吃饭();

代码实现

/*
* 抽象类实现猫狗案例
*
* */
abstract class Animal {  //创建抽象类动物
    //姓名
   private String name;
    //年龄
   private int age;

   //构造方法,无参,有参
    public Animal(){}

    public Animal(String name,int age){
        this.name = name;
        this.age = age;
    }

    //成员方法,get和sat
    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;
    }

    //抽象方法
    abstract  void eat();
}

//定义具体类猫
class Cat extends Animal{
    //成员变量继承

    //构造方法
    public Cat(){}

    public Cat(String name,int age){
        super(name, age);
    }

    //成员方法
    public void eat(){
        System.out.println(super.getName()+"吃鱼");
    }
}

//定义具体类狗
class Dog extends Animal{
    //成员变量继承

    //构造方法
    public Dog(){}

    public Dog(String name,int age){
        super(name, age);
    }

    //成员方法
    public void eat(){
        System.out.println(super.getName()+"狗吃肉");
    }
}

//测试类
class ChouXiangTest{
    public static void main(String[] args) {
        //创建对象
        //无参
        Cat c = new Cat();
        c.setName("小花");
        c.setAge(3);
        c.eat();
        System.out.println(c.getName()+"---"+c.getAge());

        //有参
        Cat c2 = new Cat("小白",5);
        c2.eat();
        System.out.println(c2.getName()+"---"+c2.getAge());

        //多态
        Animal a = new Dog();
        a.setName("小黑");
        a.setAge(5);
        a.eat();
        System.out.println(a.getName()+"----"+a.getAge());
    }
}

接口
特点:
 接口用关键字interface表示
  interface 接口名 {}
 类实现接口用implements表示
  class 类名 implements 接口名 {}
 接口不能实例化,按照多态的方式来实例化
接口的子类
 可以是抽象类,但是意义不大
 可以是具体类,要重写接口中的所有抽象方法(推荐方案)
由此可见:
A:具体类多态(几乎没有)
B:抽象类多态(常用)
C:接口多态(最常用)

//定义动物培训接口
interface AnimalTrain {
    public abstract void jump();
}

//抽象类实现接口
abstract class Dog implements AnimalTrain {
}

//具体类实现接口
class Cat implements AnimalTrain {
    public void jump() {
        System.out.println("猫可以跳高了");
    }
}

class InterfaceDemo {
    public static void main(String[] args) {
        //AnimalTrain是抽象的; 无法实例化
        //AnimalTrain at = new AnimalTrain();
        //at.jump();
        
        AnimalTrain at = new Cat();
        at.jump();  //根据方法重写的要求,执行看右边,所以输出猫的jump,猫可以跳高了
    }
}

接口成员特点
  成员变量:只能是常量,并且是静态的
  默认修饰符:public static final //自己写出默认修饰符
 构造方法:接口没有构造方法,因为接口主要是扩展功能,没有具体存在,初始化靠父类Object
 成员方法:只能是抽象方法
  默认修饰符:public abstract //自己写出默认修饰符
所有的类都默认继承自一个类:Object
类 Object 是类层次结构的根类,每个类都使用 Object 作为超类
接口名+Impl这种格式是接口的实现类格式

interface Inter {
    public int num = 10;
    public final int num2 = 20;  //不写全会默认给出
    public static final int num3 = 30;  //最终格式
    
    //错误: 需要<标识符>
    //public Inter() {}  //接口没有构造方法
    
    //接口方法不能带有主体
    //public void show() {}  //说明是抽象的

    //abstract void show(); //默认public
    public void show(); //默认abstract
}

//接口名+Impl这种格式是接口的实现类格式
/*
class InterImpl implements Inter {
    public InterImpl() {
        super();
    }
}
*/

class InterImpl extends Object implements Inter {  //继承自Object
    public InterImpl() {
        super();
    }
    
    public void show() {}
}

//测试类
class InterfaceDemo2 {
    public static void main(String[] args) {
        //创建对象
        Inter i = new InterImpl();
        System.out.println(i.num);
        System.out.println(i.num2);
        //i.num = 100;
        //i.num2 = 200;
        //System.out.println(i.num); //无法为最终变量num分配值,说明是final修饰
        //System.out.println(i.num2);//无法为最终变量num2分配值
        System.out.println(Inter.num);
        System.out.println(Inter.num2);
        System.out.println("--------------");
    }
}

接口成员特点
 成员变量;只能是常量,并且是静态的
  默认修饰符:public static final 自己手动给出
 构造方法:接口没有构造方法
 成员方法:只能是抽象方法
  默认修饰符:public abstract  自己手动给出
所有的类都默认继承自一个类:Object
类 Object 是类层次结构的根类。每个类都使用 Object 作为超类
接口名+Impl这种格式是接口的实现类格式

interface Inter {
    public int num = 10;
    public final int num2 = 20;  //没写的默认给出
    public static final int num3 = 30;  //最终格式
    
    //错误: 需要<标识符> 没有构造方法
    //public Inter() {}
    
    //接口方法不能带有主体
    //public void show() {}

    //abstract void show(); //默认public
    public void show(); //默认abstract
}

//接口名+Impl这种格式是接口的实现类格式
/*
class InterImpl implements Inter {
    public InterImpl() {
        super();
    }
}
*/

class InterImpl extends Object implements Inter {  //默认继承自Object类
    public InterImpl() {
        super();
    }
    
    public void show() {}
}

//测试类
class InterfaceDemo2 {
    public static void main(String[] args) {
        //创建对象
        Inter i = new InterImpl();
        System.out.println(i.num);
        System.out.println(i.num2);
        //i.num = 100;
        //i.num2 = 200;
        //System.out.println(i.num); //无法为最终变量num分配值是final修饰默认
        //System.out.println(i.num2);//无法为最终变量num2分配值
        System.out.println(Inter.num);
        System.out.println(Inter.num2);
        System.out.println("--------------");
    }
}

类,接口之间的关系
类与类:
  继承关系,只能单继承,可以多层继承
类与接口:
  实现关系,可以单实现,也可以多实现,并且还可以在继承一个类的同时实现多个接口
接口与接口:
  继承关系,可以单继承,也可以多继承
一个类实现多继承接口时,要重写接口多继承中的所有方法

interface Father {
    public abstract void show();
}

interface Mother {
    public abstract void show2();
}

interface Sister extends Father,Mother {  //接口可以多继承

}

//class Son implements Father,Mother //多实现
class Son extends Object implements Father,Mother {
    public void show() {
        System.out.println("show son");
    }
    
    public void show2() {
        System.out.println("show2 son");
    }
}

class InterfaceDemo3 {
    public static void main(String[] args) {
        //创建对象
        Father f = new Son();
        f.show();
        //f.show2(); //报错,方法看左边,左边没有show2
    
        Mother m = new Son();
        //m.show(); //报错,方法看左边,左边没有show
        m.show2();
    }
}

抽象类和接口的区别
成员区别
 抽象类:
  成员变量:可以变量,也可以常量
  构造方法:有
  成员方法:可以抽象,也可以非抽象
 接口:
  成员变量:只可以常量
  构造方法:没有
  成员方法:只可以抽象

关系区别
 类与类
  继承,单继承
 类与接口
  实现,单实现,多实现
 接口与接口
  继承,单继承,多继承

设计理念区别
 抽象类 被继承体现的是:”is a”的关系,抽象类中定义的是该继承体系的共性功能
 接口 被实现体现的是:”like a”的关系,接口中定义的是该继承体系的扩展功能(特有功能)

接口版猫狗案例

/*
* 需求:利用接口实现猫狗案例跳高功能
* 分析:从具体到抽象
*      猫:
*        成员变量:姓名,年龄
*        构造方法:有参无参
*        成员方法:睡觉,吃饭
*      狗:
 *       成员变量:姓名,年龄
 *       构造方法:有参无参
 *       成员方法:睡觉,吃饭
 *     动物:
 *       成员变量:姓名,年龄
 *       构造方法:有参无参
 *       成员方法:睡觉(){},吃饭()抽象类,猫狗吃的不一样
 *     调高功能:
 *        接口
* */
//实现:从抽象到具体
//调高功能
interface Jump{
    //跳高功能
    public abstract void jump();  //接口中只能用抽象的方法
}
//定义抽象动物类
abstract class Animal{
    //成员变量
    //姓名
    private String name;
    //年龄
    private int age;

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

    //成员方法
    //get和sat
    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 void sleep(){
        System.out.println("睡觉");
    }

    //吃饭定义为抽象类
    abstract void eat();
}

//定义具体类猫
class Cat extends Animal{
    //成员变量继承
    //构造方法
    public Cat(){}
    public Cat(String name,int age){
        super(name, age);
    }

    //成员方法,继承睡觉
    //重写吃饭
    public void eat(){
        System.out.println("猫吃鱼");
    }
}

//定义具体类狗
class Dog extends Animal{
    //成员变量继承
    //构造方法
    public Dog(){}
    public Dog(String name,int age){
        super(name, age);
    }

    //成员方法,继承睡觉
    //重写吃饭
    public void eat(){
        System.out.println("狗吃肉");
    }
}

//猫类实现跳高
class JumpImplCat extends Cat implements Jump{
    //成员变量继承
    //构造方法
    public JumpImplCat(){}
    public JumpImplCat(String name,int age){
        super(name, age);
    }

    //成员方法继承睡觉吃饭
    //跳高
    public void jump(){
        System.out.println("猫跳高");
    }
}

//狗类实现跳高
class JumpImplDog extends Cat implements Jump{
    //成员变量继承
    //构造方法
    public JumpImplDog(){}
    public JumpImplDog(String name,int age){
        super(name, age);
    }

    //成员方法继承睡觉吃饭
    //跳高
    public void jump(){
        System.out.println("狗跳高");
    }
}
public class JiekouText {
    public static void main(String[] args) {
        //测试无参构造猫
        JumpImplCat cat = new JumpImplCat();
        cat.setName("哆啦A梦");
        cat.setAge(3);
        cat.eat();
        cat.sleep();
        cat.jump();
        System.out.println(cat.getName()+"----"+cat.getAge());

        //测试有参构造狗
        JumpImplDog dog = new JumpImplDog("小白",3);
        dog.eat();
        dog.sleep();
        dog.jump();
        System.out.println(dog.getName()+"-----"+dog.getAge());
    }
}

Day10

引用类型作为方法的形参
  类名:(匿名对象的时候其实我们已经讲过了)需要的是该类的对象
  抽象类:需要的是该抽象的类子类对象
  接口:需要的是该接口的实现类对象

//类名作为方法的形式参数
class Student {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class StudentDemo {
    public void method(Student s) { //ss; ss = new Student();  Student s = new Student();
    s.study();
    }
}

class StudentTest {
    public static void main(String[] args) {
        //需求:我要测试Student类的study()方法
        Student s = new Student();  //创建对象
        s.study();  //调用方法
        System.out.println("----------------");
        
        //需求2:我要测试StudentDemo类中的method()方法
        StudentDemo sd = new StudentDemo();
        Student ss = new Student();
        sd.method(ss);
        System.out.println("----------------");
        
        //匿名对象用法
        new StudentDemo().method(new Student());
    }
}

//抽象类作为方法的形式参数
abstract class Person {
    public abstract void study();
}

class PersonDemo {
    public void method(Person p) {//p; p = new Student();  Person p = new Student(); //多态
        p.study();
    }
}

//定义一个具体的学生类
//抽象类作为方法的形式参数
class Student extends Person {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class PersonTest {
    public static void main(String[] args) {
        //目前是没有办法的使用的
        //因为抽象类没有对应的具体类
        //那么,我们就应该先定义一个具体类
        //需求:我要使用PersonDemo类中的method()方法
        PersonDemo pd = new PersonDemo();
        Person p = new Student();
        pd.method(p);
    }
}
//接口作为方法的形式参数
interface Love {
    public abstract void love();
}

class LoveDemo {
    public void method(Love l) { //l; l = new Teacher();  Love l = new Teacher(); 多态
        l.love();
    }
}

//定义具体类实现接口
class Teacher implements Love {
    public void love() {
        System.out.println("老师爱学生,爱Java");
    }
}

class TeacherTest {
    public static void main(String[] args) {
        //需求:我要测试LoveDemo类中的love()方法
        LoveDemo ld = new LoveDemo();
        Love l = new Teacher();
        ld.method(l);
    }
}

引用类型作为返回值
  类:返回的是该类的对象
  抽象类:返回的是该抽象类的子类对象
  接口:返回的是该接口的实现类的对象

//类最为返回值
class Student {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class StudentDemo {
    public Student getStudent() {
        //Student s = new Student();
        //Student ss = s;
        
        //Student s = new Student();
        //return s;
        return new Student();
    }
}

class StudentTest2 {
    public static void main(String[] args) {
        //需求:我要使用Student类中的study()方法
        //但是,这一次我的要求是,不要直接创建Student的对象
        //让你使用StudentDemo帮你创建对象
        StudentDemo sd = new StudentDemo();
        Student s = sd.getStudent(); //new Student(); Student s = new Student();
        s.study();
    }
}
//抽象类作为返回值
abstract class Person {
    public abstract void study();
}

class PersonDemo {
    public Person getPerson() {
        //Person p = new Student();
        //return p;
        
        return new Student();
    }
}

class Student extends Person {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class PersonTest2 {
    public static void main(String[] args) {
        //需求:我要测试Person类中的study()方法
        PersonDemo pd = new PersonDemo();
        Person p = pd.getPerson(); //new Student();  Person p = new Student(); 多态
        p.study();
    }
}
//接口作为返回值
interface Love {
    public abstract void love();
}

class LoveDemo {
    public Love getLove() {
        //Love l = new Teacher();
        //return l;
        
        return new Teacher();
    }
}

//定义具体类实现接口
class Teacher implements Love {
    public void love() {
        System.out.println("老师爱学生,爱Java");
    }
}

class TeacherTest2 {
    public static void main(String[] args) {
        //如何测试呢?
        LoveDemo ld = new LoveDemo();
        Love l = ld.getLove(); //new Teacher(); Love l = new Teacher(); 多态
        l.love();
    }
}

链式编程
每次调用完毕后返回的是一个对象(只有对象才能继续调方法)

class Student {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class StudentDemo {
    public Student getStudent() {
        return new Student();
    }
}

class StudentTest3 {
    public static void main(String[] args) {
        //如何调用的呢?
        StudentDemo sd = new StudentDemo();
        //Student s = sd.getStudent();
        //s.study();
                //相当于下边的
        sd.getStudent().study();
    }
}


 其实就是文件夹
作用
 把相同的类名放到不同的包中
 对类进行分类管理
 举例:
  学生:增加,删除,修改,查询
  老师:增加,删除,修改,查询
  ...

方案1:按照功能分
 cn.itcast.add
 AddStudent
 AddTeacher

cn.itcast.delete
 DeleteStudent
 DeleteTeacher

cn.itcast.update
 UpdateStudent
 UpdateTeacher

cn.itcast.find
 FindStudent
 FindTeacher

方案2:按照模块分
 cn.itcast.teacher
 AddTeacher
 DeleteTeacher
 UpdateTeacher
 FindTeacher

cn.itcast.student
 AddStudent
 DeleteStudent
 UpdateStudent
 FindStudent
包的定义
 package 包名;
  多级包用.分开即可

注意事项:
 package语句必须是程序的第一条可执行的代码
 package语句在一个java文件中只能有一个
 如果没有package,默认表示无包名

带包的编译和运行:
 手动式
  编写一个带包的java文件
  通过javac命令编译该java文件
  手动创建包名
  把b步骤的class文件放到c步骤的最底层包
  回到和包根目录在同一目录的地方,然后运行
  带包运行

自动式
  编写一个带包的java文件
  javac编译的时候带上-d即可
  javac -d . HelloWorld.java
  回到和包根目录在同一目录的地方,然后运行
  带包运行

导包
 格式:import 包名;
 这种方式导入是到类的名称,注意:我们用谁就导谁
 例:import cn.itcast.Demo //Demo为类名

package,import,class的顺序关系
 package > import > class
  Package:只能有一个
  import:可以有多个
  class:可以有多个,以后建议是一个

权限修饰符的访问
     本类  同一个包下(子类和无关类)  不同包下(子类) 不同包下(无关类)
private   Y
默认    Y     Y
protected Y     Y            Y
public    Y      Y             Y       Y

你可能感兴趣的:(2022-02-23)