day20---前19天内容总结

作业

1.语言基础

1.Java开发环境、JVM、JRE、JDK

  • Java开发环境

    • 编译运行过程:

      • 编译器:.Java源文件,经过编译,生成.class字节码文件

      • 运行期:JVM加载.class并运行

        特点:跨平台,一次编译到处使用

  • JVM:Java虚拟机

    加载.class并运行.class

  • JRE:Java运行环境

    除了包含JVM以外还包含运行Java程序所必须的环境

  • JDK:Java开发工具包

    除了包含JRE以外还包含了开发Java程序所必须的命令工具

    JDK=JRE+编译、运行等命令工具

    说明:

    1. 运行Java程序的最小环境为JRE

    2. 开发Java程序的最小环境为JDK

  • 驼峰命名

    1. 大驼峰

      • 特点:第一个字母大写,后边也大写

      • 应用:类名、函数名、属性名、命名空间

    2. 小驼峰

      • 特点:第一个字母小写,后边大写

      • 应用:变量

2.变量、八种基本数据类型、类型间的转换

  • 变量:

    1. 声明:相当于开户

    2. 初始化:第一次赋值,相当于给账户存钱

    3. 使用:使用账户的钱

      int a;
      int a,b,c;
      //初始化
      int a =250;
      int b;
      b=1000;
      //使用
      int a=5;
      int b=a+10;
      System.out.println(b);
    4. 变量在用之前必须声明并初始化

    5. 命名:

      • 只能包含数字、字母、_和$符号,且不能以数字开头

      • 严格区分大小写

      • 不能使用关键字

      • 允许中文名,但不建议,建议“英文的见名知意”

  • 八种基本数据类型

    int\long\double\boolean\char\byte\float\short

    • int:整型,4个字节,-21个多亿到21个多亿

      • 整数直接量默认为int类型,但是不能超范围,否则编译错误

      • 两个整数相除,结果还是整数,小数位无条件舍去

      • 整数运算时,若超出int范围则发生溢出(溢出不是错误,但需要避免)

    • long:长整型,8个字节

      • 长整型直接量需要在数字后面加L或者l

      • 运算时若可能溢出,建议在第一个数字后加L

    • double:浮点型,8个字节

      • 浮点数直接量默认为double型,若想表示float须在数字后面加F和f

      • double与float型数据参与运算时,有可能出现舍入误差,精准场合不能使用

      • float是单精度类型,精度是8位有效数字,取值范围是10的-38次方到10的38次方,float占用四个字节的存储空间

        double是双精度类型,精度是17位有效数字,范围是10的-308次方到10的308次方,double占用8个字节的存储空间

    • boolean:布尔型,1个字节

    • char:字节型,2个字节

      • 采用Unicode字符集,一个字符对应一个码

        表现的形式是字符char,但是本质上是码int(0到65535之间)

        ASCLLII码:’a‘--97 ‘A’--65 ‘0’---48

      • 字符型直接量必须放在单引号中,且只能有1个

      • 特殊符号需通过\来转义

  • 类型间的转换

    • 基本类型由小到大为:

      byte\short\char->int->long->float->double

    • 注意:这里的大小指的不是占了多少字节的大小而是取值范围,且boolean类型不参与类型转换

      byte、short、char相互之间不转换,它们参与运算首先转换为int类型

    • 两种方式:

      • 自动/隐式类型转换:小类型到大类型,范围小的数据类型直接转换为范围大的数据类型

      • 强制类型转换:大类型到小类型

        int a =5;
        long b= a;//自动类型转换
        int c =(int)b;//强制类型转换


        long d = 5;//自动类型转换
        double e = 5;//自动类型转换



        long f = 10000000000L;
        int g = (int)f; //强制类型转换
        System.out.println(g); //1410065408,强转有可能发生溢出
        double h = 25.987;
        int i = (int)h; //强制类型转换
        System.out.println(i); //25,强转有可能丢失精度
      • 两点规则

        • 整数直接量可以直接赋值给byte(范围为-128到127之间),short,char,但是不能超出范围

        • byte,short,char型数据参与运算时,系统一律自动将其转换为int在运算

          byte b1 = 5; //byte的范围为-128到127之间
          byte b2 = 6;
          byte b3 = (byte)(b1+b2);

          System.out.println(2+2);     //4
          System.out.println(2+'2');   //52,2加上'2'的码50
          System.out.println('2'+'2'); //100,'2'的码50,加上'2'的码50

    ###

3.运算符、分支结构

  • 运算符

    1. 普通四则运算符+,-,*,/

    2. 取余%,余数为0表示整除

    3. 自增自减运算符

      1. 可以改变变量自身的值

      2. 前缀式:++a,先改变自身的值,再参与运算

      3. 后缀式:a++,先参与运算,再改变自身的值

      4. 注意:

        1. 单独使用时,两者的值相同

        2. 被使用时,++a的值为a+1;a++的值为a

      5. 比较运算符

        1. 比较运算符最终的结果是布尔类型的

        2. ==两边的值是否相等,!=为不相等

      6. 逻辑运算符

        1. &&:与

        2. ||:或

        3. !:非

      7. 赋值

        =,+=,-=,*=,/=,%=

      8. 拼接功能

        1. 两边都为数字,做加法运算

        2. 若两边出现字符串,则字符串连接

        3. 任何类型与字符串相连,结果都会变为字符串类型---同化作用

      9. 条件运算符:三目运算符

        1. 语法:Boolean?数1:数2

        2. 执行过程:

          整个表达式是有值的,值只能是?后面的值之一

          计算Boolean的值:

          若为true,整个表达式的值为?号后的数1

          若为false,整个表达式的值为:号后的数2

  • 分支结构

    1. if(){}else(){}

    2. 嵌套分支结构

      if(判断条件1){
         符合判断条件1,执行此处代码,不符合,继续向下判断
      }else if(判断条件2){
         符合判断条件2,执行此处代码,不符合,继续向下判断
      }else if(判断条件3){
         符合判断条件3,执行此处代码,不符合,继续向下判断
      }else{
         保底选项,以上条件均不符合的情况下,执行此处代码
      }
  • 选择结构

    1. 小括号中变量支持的类型: byte\ short\ char\ int\ String\枚举类型

    2. 注意: 如果配置了default默认选项,而且没有任何的case被匹配到,就会执行default这个“保底选项”,default可以写在switch里的任何地方,但无论写在哪儿,都一定是先匹配case,当所有case都未匹配时才执行

    3. case的个数 是否加break 是否加default全部都是可选的,根据自己的具体业务做决定

    4. 小括号中变量的类型必须与case后value的类型一致

    5. 执行顺序:先拿着变量的值,依次与每个case后的值做比较,如果相等,就执行case后的语句 若这个case后没有break,就会继续向下执行下一个case,如果一直没有遇到break,就会发生穿透现象,包括default

    6. switch (变量名){
                 case value1 : 操作1;break;//可选
                 case value2 : 操作2;break;//可选
                 case value3 : 操作3;break;//可选
                 case value4 : 操作4;break;//可选
                 default:保底选项;//可选
            }

 

4.循环结构

  • 循环三要素:

    • 循环变量的初始化

    • 循环变量的条件(以循环变量为基础)

    • 循环变量的改变

      循环变量:在整个循环变量中反复改变的那个数

  • 循环结构

    • while结构

      • 语法:

        while(boolean){
        语句块
        }
      • 执行过程

        1. 先判断boolean的值,若为true则执行语句块

        2. 再判断boolean的值,若为true则再执行语句块

        3. 再判断boolean的值,若为true则再执行语句块,如此反复,直到boolean的值为false时,while循环结束

    • do...while结构

      • 实例:猜大小

        import java.util.Scanner;
        public void Guessing{
           public static void main(String[] args){
               Scanner scan=new Scanner(System.in);
               int num=(int)(Math.random()*1000+1);
               int guess;
               do{
                   System.out.println("请输入一个数");
                   guess=scan.nextInt();
                   if(guess>num){
                       System.out.println("大了");
             
                  }else if(guess<num){
                       System.out.println("小了")
                  }else{
                        System.out.println("猜对了")
                  }
              }
               while(guess!=num)
          }
        }
    • for结构

      1. 注意:

        1. 写法小窍门:从哪儿开始,到哪儿结束,循环变量如何变化

        2. for循环执行的次数,取决于循环变量可以取到几个值

        3. for中的循环变量times的作用域仅在当前for中

      2. for...each:

        不使用下标变量就可以顺序的遍历整个数组

  • 三种结构如何选择

    • 先看循环是否与次数相关

      • 相关:---------for

      • 无关:---------再看要素1,3是否相同(

        第一要素:开始条件;

        第二要素:循环条件;

        第三要素:更改条件)

        • 若相同------------------直接上do...while

          • 先循环后判断

          do-while循环一定会执行一次,然后再判断,如果符合条件,再执行后面的循环

        • 若不同------------------while

          • 先判断再循环(数字叠加)

  • break---continue

    • 作用:

      主要作用都是停止循环

    • 区别:

      • 注意:

      1. 只能在循环体和switch语句体内使用break

      2. 不管是哪种循环,一旦在循环体中遇到break,系统将完全结束循环,开始执行循环之后的代码。

      3. 当break出现在循环体中的switch语句体内时,起作用只是跳出该switch语句体并不能终止循环体的执行。若想强行终止循环体的执行,可以在循环体中,但并不在switch语句中设置break语句,满足某种条件则跳出本层循环体。

      • continue语句的作用是跳过本次循环体中剩下尚未执行的语句,立即进行下一次的循环条件判定,可以理解为只是中止(跳过)本次循环,接着开始下一次循环。

      • 注意:

      1. continue语句并没有使整个循环终止。

      2. continue 只能在循环语句中使用,即只能在 for、while 和 do…while 语句中使用

  • 嵌套循环

    1. 嵌套for循环

    外层循环控制的是轮数,内层循环控制的是每一轮中执行的次数 对于图形而言,外层循环控制的是行数,内层循环控制的是列数

5.数组

  1. 创建:

    1. 根据数组的类型与长度开辟一块连续的内存空间

    2. 对数组中的每个元素进行初始化,比如int数组的默认值就是0

    3. 生成数组唯一的一个地址值,交给应用类型变量a来保存

    4. 后续可以根据数组的下标再来操作数组中的具体元素 注意: 数组名a这个变量,保存的是数组的地址,不是数组中的具体元素

  2. 数组的工具类Arrays

    1. toString(数组名) : 除了char类型的数组以外,其他类型的数组想要查看具体元素,需要使用本方法,否则打印的是地址值

    2. copyOf(原数组名,新数组的长度) : 用来实现数组的复制 扩容 缩容 如果新数组的长度 > 原数组长度,就扩容,反之,则缩容,如果两者长度一致,就是普通的复制数组 注意:一定是创建了新数组,而不是对原数组的长度做操作

  3. 复制:

    • 方法一:System.arraycopy(a,0,b,0,4);

    a:源数组

    0:源数组开始复制的位置

    b:目标数组

    0:目标数组开始接受复制的位置

    4:复制的长度

    • 方法二:引入小零件Array , Array.copyOf(a,b)

      a:源数组

      b:新数组长度

  4. 排序:

    升序:Arrays.sort(arr)

    倒序:从最后一项开始

    for (int i=a.length-1;i>=0;i--){
               System.out.println(a[i]);
          }

6.方法

  1. 定义

    • 用于封装一段特定的逻辑功能

    • 方法尽可能独立,只干一件事

  2. 五要素:

    1. 修饰词 public static

    2. 返回值类型

      • 无返回值:类型一般设计为void

      • 有返回值:类型设计为特定的数据类型

      • 有无返回值的区分:

        方法被调用后数据是否还会被使用

    3. 方法名(参数列表){方法体}

    4. 注意:方法定义不能套娃,只能并列;但是方法调用可以套用

    5. 调用:有无返回值

      • 无返回值:方法名(有参传参)

         //无返回值,无参数
           public  static void say(){
               System.out.println("雷浩啊");
          }

        //调用
        say();
        //无返回值,有参数
           public static void plus(int gold){
               double mon= (double) (0.068)*gold;
               System.out.println("需要花费¥"+mon+"元");

          }
        //调用
        plus(1000);

         

      • 有返回值:数据类型 变量 =方法名(有参传参)

         //有返回值,无参数
        public static double getNum( ){
           return 8.88;

          }
        //调用
        double b=getNum();
        System.out.println(b)
         //有返回值,无参数---数组返回值
           
           public static  int[] testArray(){
               int [] arr=new int[10];
               for (int i =0;i<arr.length;i++){
                   arr[i]=(int)(Math.random()*100);

              }
               return arr;
          }
          //调用并排序
        import java.util.Arrays;
        int [] t=testArray();
               System.out.println(t.length);
               System.out.println("");
               for (int i=0;i<t.length;i++){
                   System.out.println(t[i]);
              }
               Arrays.sort(t);
               System.out.println("");
               for (int i=0;i<t.length;i++){
                   System.out.println(t[i]);
              }
           
            //有返回值,有参数
           public static  int maxPlus(int num1,int num2){
               int num =num1+num2;
               return num;
          }
        //调用
        int a=maxPlus(5,6);
               System.out.println(a);
        //或者
        int e=5,f=6;
               int b=maxPlus(e,f);
               System.out.println(b);
    6. return

      return 值:结束方法并将值返回给调用方

      return;结束发方法的执行

 

2.面向对象

1.类和对象、方法的重载

1.类

  • 定义:类别/类型,代表一类个体

  • 关系:类是对象的模板,对象是类的具体实例

  • 类是自己创建的引用数据类型

  • 创建:

    • 类的创建

      定义类通过关键字class来定义,类是一类事物的抽象

      public class a {    }//a为类名

       

    • Java中一个文件只包含一个类

    • 访问类,打点.调用---------zs.

2.对象

  • 定义:软件中真实存在的单个个体/东西

  • 对象的属性/特征------------------变量

  • 对象的行为/功能------------------方法

  • 对象之间相互独立,互不影响

  • 类是对象的模板,对象是类的具体实例

  • 对象具有类的所有属性和功能

  • 创建:

    对象的创建

    通过new关键字触发构造函数生成,对象是根据类创建出来的实例,因此把创建对象也成为“实例化”

    Student zs=new Student();Student:数据类型zs:引用类型变量,后期简称为引用=:指向new Student:对象
  • 访问类,打点.调用---------zs.

3.方法的重载

  • 英文命名:overload/overloading

    package ooday01;public class Aoo {        
       void show(){};    
       void show(String name){};    
       void show(int age){};    
       void show(String name ,int age ){};    
       void show(int age,String name){};    //错误    
       //void show(){return 0};   //编译错误,重载与返回值类型无关  
       // void show(String address){};//编译错误,重载与参数名称无关}
  • 作用:更加方便的使用方法

  • 方法的签名=方法名+参数列表

  • 发生在同一类中,方法名相同,参数列表不同

  • 编译器在编译时会根据方法的签名自动绑定方法

2.构造方法、this

1.构造方法

  • 又名构造函数,构造器

  • 作用:给成员变量赋初始值

  • 调用:在创建(new)对象时被自动调用

  • 构造方法可以重载

  • 与类同名,没有返回值类型

    package ooday02;

    public class Student {
       String name;
       int age;
       String address;

       void sayHi() {
           System.out.println("我的名字是" + name + ",今年" + age + "岁了,家住" + address);
      }    //构造函数    

       Student(String name1, int age1, String address1) {
           name = name1;
           age = age1;
           address = address1;
      }
    }//调用package ooday02;

    public class TestStudent {
       public static void main(String[] args) {
           Student zs = new Student("张三", 18, "jiangsu");
           zs.sayHi();
           Student ls = new Student("里斯", 20, "hebei");
           ls.sayHi();
      }
    }

2.this

  • 只能用在方法中 ,方法中访问成员变量之前默认有个this

  • 指代当前对象,哪个对象调用它就指代哪个对象

  • this.成员变量名-------访问成员变量

  • 局部变量,只在当前方法范围

  • 成员变量与局部变量可以同名

    1. 使用的时候默认就近原则

    2. 访问成员变量时this不能省略

  • 实例

    public class Student { String  name;   int age;   String address; 
       void.sayHi(){System.out.println("我的名字是"+name+",今年"+age+"岁了,家住"+address);   }    
       Student(name,age,address){
           this.name =name;        
           this.age=age;        
           this.address=address   }}
    //调用public
    class ConsDemo {    public static void main (String[]  args) {
        Student zs=new Student("张三",18,"jiangsu");        
    zs.sayHi();
        Student ls=new Student("里斯",20,"hebei");
        s.sayHi(); }}

3.引用类型数组、继承、super

1.引用类型数组

与基本类型数组的区别

  1. 给数组元素赋值必须new一下

  2. 若想访问对象数据必须通过数组元素打点

    Student stus=new Student[3];stus[0]=new Student("zhangsan",23,"ls");
    stus[1]=new Student('lisi',25,"gh");
    stus[2]=new Student("wangwu",19,"fh");
    System.out.println(stus[0].name);
    for(int i=0;i<stus.length;i++){    System.out.println(stus[i].name)}

2.继承

  • 作用:代码复用

  • 通过extends来继承

  • 继承要符合is(是)的关系,不能为了复用代码就乱继承

  • 超类/父类:共有的属性和行为

  • 派生类/子类:特有的属性和行为

  • 派生类/子类既能访问自己的,也能访问超类,但是超类不能访问派生类

  • 一个超类可以有多个派生类,但是派生类只能有一个超类

  • 继承具有传递性

  • 继承的是超类中的成员变量和普通方法,而不包括构造方法

    超类的构造方法是被派生类通过super来调用

  • Java规定:构造派生类之前必须先构造超类

    • 在派生类的构造方法中若没有调用超类的构造方法,则默认super()调用超类的无参构造方法

    • 在派生类的构造方法中若自己调用了超类的构造方法,则不再默认提供

    • super()调用超类构造方法,必须位于派生构造方法的第一行

3.super

  • 定义:指代当前对象的超类对象

  • 用法:

    1. super.成员变量名-------------访问超类的成员变量

    2. super.方法名()-----------------调用超类的构造方法

    3. super()----------------------------调用超类的构造方法

4.向上造型、方法的重写

1.向上造型

  1. 超类型的引用指向派生类的对象

  2. java规定:能点出什么,看引用类型

  3. 意义:实现代码复用

    1. 当多种角色能干的事是同一件时,可以将那多种角色造型到超类数组中,统一访问

2.方法的重写

  • 发生在父子类中,方法名相同,参数列表相同

  • 重写方法被调用时,看对象的类型

  • 重写遵循“两同两小一大”原则

    • 两同:

      1. 方法名相同

      2. 参数列表相同

    • 两小:

      1. 派生类方法的返回值类型小于或等于超类方法的

        1. void和基本类型时,必须相等

        2. 引用类型时,小于或等于

      2. 派生类方法抛出的异常小于或等于超类方法的

    • 一大:

      派生类方法的访问权限大于或等于超类方法的

3.重写与重载的区别

  1. 重写(override):发生在父子类中,方法名相同,参数列表相同

    --------用于在派生类中修改超类中所声明的方法

  2. 重载(overload):发生在同一类中,方法名相同,参数列表不同

    --------完全不同的方法,只是方法名正好相同

5.package和import、访问控制修饰符、static、final

1.package

  1. package:声明包

    1. 避免类的命名冲突

    2. 同包的不能同名

    3. 类的全称:包名.类名

    4. 包名常常用层次结构,建议所有字母都小写

2.import

  1. 同包中的类可以直接访问 不同包中的类不能直接访问,若想访问:

    1. 先import声明类,再访问类------建议

    2. 类的全称-----------------------------太繁琐,不建议

3.访问控制修饰符

  1. 作用:保证数据的安全

  2. public:公开的,任何类

  3. private:私有的,本类

  4. protected:受保护的,本类、派生类、同包类

  5. 默认的:什么也不写,本类、同包类

    说明:

    1. 类的访问权限只能是public或默认的

    2. 类中成员的访问权限如上4种都可以

    3. 访问权限由高到低为:public>protected>默认>private

4.static

1.成员变量(实例变量、静态变量)
  1. 实例变量:

    1. 没有static修饰

    2. 属于对象

    3. 存储在堆中

    4. new多少个,存在多少个

    5. 通过引用(对象)点访问

    6. 代码:

      Student zs=new ...zs.name/age/address
  2. 静态变量:

    1. 由static修饰

    2. 属于类

    3. 存储在方法区

    4. 只存一份

    5. 通过类点访问

    6. 何时用:所有对象所共享的数据(图片、音频、视频等)

    7. 代码:

      class Aoo {    int a;}//调用Aoo.a
  3. 区别:

    1. 初始化:静态块-----初始化静态变量;

      构造方法--初始化实例变量;

2.静态方法
  1. 由static修饰

  2. 属于类,存储在方法区中,只有一份

  3. 常常通过类名点来访问

  4. 静态方法中没有隐式this传递

  5. 何时用:方法的操作与对象无关

  6. public class StaticDemo {
       public static void main (String[] args){
           Moo.test();
      }
    }
    //演示静态方法
    class Moo {
       int a;//实例变量(对象点来访问)
       int b;//静态变量(类名点来访问)
       void show() {//有隐式this
           System.out.println(this.a);
           System.out.println( Moo.b);
           
      }
       static void tset(){//没有隐式this
       
           
            //System.out.println(this.a);//编译错误.原因:静态方法中没有隐式this传递,没有this意味着没有对象,而实例变量a必须通过对象点来访问
           System.out.println( Moo.b);
      }
    }

    //演示静态方法什么时候用
    class overwatch{
       int a;  //对象属性a
       void show(){
           
             //在show方法中用到了对象的属性a,意味着show()方法与对象有关,所以不能设计为静态方法
           System.out.println(a);
         
      }
       //在plus方法中没有用到对象的属性a,意味着plus()方法与对象无关,所以可以设计为静态方法
       static int plus(int num1,int num2){
           int num=num1+num2;
           return num;
      }
    }
3.静态块
  1. 由static修饰

  2. 属于类,在类中被加载期间自动执行,一个类只能被加载一次,所以静态块只执行一次

  3. 何时用:加载/初始化静态资源(图片、音频、视频等)

  4. 代码

    public class static {    
       public static void main(String[] args){        
           Aoo o1=new Aoo;        
           Aoo o2=new Aoo;   }   }
    //演示静态块
    class Aoo {    
       static {          System.out.println("静态块");   }    
       Aoo(){        System.out.println("构造方法");   }}
4.补充
  1. 数据(成员变量)私有化(private),行为(方法)大部分公开化(public)

  2. 成员变量分两种:

    1. 实例变量:没有static修饰,属于对象的,存储在堆中,有几个对象就有几份 通过引用(对象)点来访问

    2. 静态变量:由static修饰,属于类的,存储在方法区中,只有一份 通过类名点来访问

6.static final常量、抽象方法、抽象类

1.static final常量

  1. 必须“声明同时初始化”

  2. 类名点来访问,不能被改变

  3. 建议:常量所有字母必须大写,多个单词用_隔开

  4. 编译器在编译时常会将常量直接替换成具体的数值,效率高

  5. 何时用:数据不变,经常使用

  6. 代码

    public Aoo {    public static int a=5;    public static final int b=5;}

2.抽象方法

  1. 由abstract修饰

  2. 只有方法的定义,没有具体实现的方法,连{}都没有

3.抽象类

  1. 由abstract修饰

  2. 包含抽象方法的类必须是抽象类

  3. 抽象类不能被实例化(new 对象)

  4. 抽象类是需要被继承的,派生类:

    1. 重生所有抽象对象------------------变不完整为完整

    2. 也声明为抽象类---------------------一般不这么用

  5. 抽象类的意义:

    1. 封装共有的属性和行为----------------代码复用

    2. 为所有派生类提供统一的类型-------向上造型

    3. 可以包含抽象方法,为所有派生类提供统一的入口(能点出来),

      派生类的行为不同,但入口是一致的,同时相当于定义了一个标准(强制重写)

7.成员内部类、匿名内部类

1.成员内部类

  1. 应用率低

  2. 类中套类,外面的成为外部类,内部的成为内部类

  3. 内部类只服务于外部类,对外不具备可见性

  4. 内部类对象通常在外部类创建

  5. 内部类中可以直接访问外部类的成员(包括私有的)

    内部类有个隐式的引用指向了创建它的外部类对象:外部类名.this

2.匿名内部类

  1. 应用率高,大大简化代码

  2. 若想创建一个类(派生类)的对象,并且对象只被创建一次,可以做成匿名内部类

  3. 在匿名内部类默认外面的变量为final的---Java规定

  4. 内部类有独立的.class吗?答:有

8.接口

  1. 是一种引用类型数据

  2. 由interface定义

  3. 只能包含常量和抽象方法

  4. 接口不能被实例化(new对象)

  5. 接口是需要被实现/继承的,实现类/派生类

    ---必须重写所有方法

  6. 一个类可以实现多个接口,用逗号分隔,若又继承又实现时,应先继承后实现

  7. 接口可以继承接口

    //接口的演示
    public class InterfaceDemo {
       public static void main(String[] args) {
           //Inter5 o1 = new Inter5(); //编译错误,接口不能被实例化
           Inter5 o2 = new Doo(); //向上造型(可以造型为它所实现的接口)
           Inter4 o3 = new Doo(); //向上造型
      }
    }

    //演示接口继承接口
    interface Inter4{
       void show();
    }
    interface Inter5 extends Inter4{
       void test();
    }
    class Doo implements Inter5{
       public void test(){}
       public void show(){}
    }

    //演示接口多实现
    interface Inter2{
       void show();
    }
    interface Inter3{
       void test();
    }
    abstract class Boo{
       abstract void say();
    }
    class Coo extends Boo implements Inter2,Inter3{
       public void show(){}
       public void test(){}
       public void say(){}
    }

    //演示接口的实现
    interface Inter1{
       void show(); //访问权限默认是public
       void test();
    }
    class Aoo implements Inter1{
       public void show(){} //重写接口中的抽象方法,访问权限必须是public
       public void test(){}
    }

    //演示接口的语法
    interface Inter{
       public static final int NUM = 5; //接口中成员的访问权限只能是public的
       public abstract void show();
       int COUNT = 6; //默认public static final
       void say(); //默认public abstract
       //int number; //编译错误,常量必须声明同时初始化
       //void test(){} //编译错误,抽象方法不能有方法体
    }

     

9.多态

  1. 意义:

    1. 同一类型的引用指向不同的对象时,有不同的实现---所有抽象方法都是多态的

      -----行为的多态

    2. 同一个对象被造型为不同类型时,有不同的功能---所有对象都是多态的

      -----对象的多态

  2. 向上造型/自动类型转换

    1. 超类型的引用指向派生类的对象

    2. 能点出什么,看引用类型

    3. 能造型成为的数据类型:超类+所实现的接口

  3. 强制类型转换,成功的条件只有如下两种

    1. 引用所指向的对象,就是该类型

    2. 引用所指向的对象,实现了该接口或者继承了该类

  4. 强转时若不符合上述条件,则发生ClassCastException类型转换异常;因此强转前先通过instanceof判断引用的对象是否是该类型

    public class MultiTypeDemo {
       public static void main(String[] args) {
           Aoo o = new Boo(); //向上造型
           Boo o1 = (Boo)o; //引用o指向的对象就是Boo
           Inter o2 = (Inter)o; //引用o指向的对象实现了Inter接口
           //Coo o3 = (Coo)o; //运行时发生ClassCastException类型转换异常
           if(o instanceof Coo){ //false
               Coo o4 = (Coo)o;
          }else{
               System.out.println("o不是Coo类型");
          }
      }
    }

    interface Inter{
    }
    class Aoo{
    }
    class Boo extends Aoo implements Inter{
    }
    class Coo extends Aoo{
    }

     

10.内存管理、面向对象总结、String入门

1.内存管理

  • 由JVM来管理

  • 堆:new出来的对象(包括成员变量,即实例变量)

    • 垃圾:没有任何引用所指向的对象

      垃圾回收器(GC)不定时到内存中清扫垃圾,回收过程是透明的(看不到的),不一定一发现垃圾就立刻回收,通过调用System.gc()可以建议JVM尽快调用GC回收

    • 实例变量的生命周期:

      创建(new)对象时存储在堆中,对象被回收时一并被回收

    • 内存泄漏:不再使用的对象没有被及时回收,严重的泄露会导致系统的崩溃

      建议:不再使用的对象应及时将引用设置为null

  • 栈:存储正在调用的方法中的局部变量(包括方法的参数)

    • 调用方法时,会在栈中为该方法分配一块对应的栈帧,栈帧中存储局部变量(包括方法的参数),方法调用结束时,栈帧会被自动清除,局部变量一并被清除

    • 局部变量的生命周期:

      调用方法时存储在栈中,方法调用结束时与栈帧一并被清除

  • 方法区:

    • 存储.class字节码文件(包括静态变量、所有方法)

    • 方法只有一份,通过this来区分具体的访问对象

  • 成员变量:写在类中,方法外----有默认值

  • 局部变量:方法中------------------没有默认值

  • 数组也是一个对象,所以数组对象也存储在堆中,将数组的元素当作成员变量一并存储在堆中

2.面向对象总结

  1. 封装

    • 类:封装的是对象的行为和属性

    • 方法:封装的是具体的业务逻辑的实现

    • 访问控制修饰符:封装的是具体的访问的权限,以保护数据安全

  2. 继承

    • 作用:代码复用

    • 超类:所有派生类所共有的行为和属性

      接口:部分派生类所共有的行为和属性

      派生类:派生类所特有的行为和属性

    • 单一继承,多接口实现,具有传递性

  3. 多态:

    • 行为多态:所有抽象方法都是多态的(通过方法的重写实现的)】

    • 对象多态:所有对象都是多态的(通过向上造型来实现)

    • 向上造型、强制类型转换、instanceof判断

     

3.String入门

  1. String字符串类型

    • java.lang.String使用final修饰,不能被继承

    • Java中的String在内存中采用Unicode编码方式,任何一个字符占用两个字节的编码

    • 字符串底层封装的是一个字符数组

    • 字符串一旦创建,对象内容永远无法改变,但字符串引用可以重新赋值---不变对象

  2. 常量池:

    • Java对字符串有一个优化措施:字符串常量池(堆中)

    • java推荐我们使用字面量/直接量方式来创建字符串,并且会缓存所有以字面量/直接量的形式创建的字符串对象到常量池,当使用相同字面量字符串再创建对象时,将复用常量池的对象以减小内存开销,从而避免内存堆积大量内容相同的字符串对象

    • package ooday10;
      //String的演示
      public class StringDemo {
         public static void main(String[] args) {
             String s1 = "123abc"; //堆中创建一个123abc对象,常量池中存储这个对象的引用

             //编译器在编译时,若发现是两个字面量连接,
             //则直接运算好并将结果保存起来,如下代码相当于String s2="123abc";
             String s2 = "123"+"abc"; //复用常量池中的123abc对象
             System.out.println(s1==s2); //true

             String s3 = "123";
             //因为s3不是字面量,所以并不会直接运算结果
             String s4 = s3+"abc"; //会在堆中创建新的123abc对象,而不会重用常量池中的对象
             System.out.println(s1==s4); //false







             /*
               使用字面量来创建字符串对象时,JVM会检查常量池中是否有该对象:
                1)若没有,则会创建该字符串对象并存入常量池中
                2)若有,则直接将常量池中的对象返回(不会再创建新的字符串对象)
              */
             /*
             String s1 = "123abc"; //常量池还没有,因此创建该字符串对象,并存入常量池
             String s2 = "123abc"; //常量池中已经有了,直接重用对象
             String s3 = "123abc"; //常量池中已经有了,直接重用对象
             //引用类型==,比较地址是否相同
             System.out.println(s1==s2); //true
             System.out.println(s1==s3); //true
             System.out.println(s2==s3); //true

             s1 = s1+"!"; //创建新的字符串对象并将地址赋值给s1
             System.out.println(s1==s2); //false,因为s1为新对象的地址,与s2不同了
             */

        }
      }

       

3.API基础和二进制

1.String常用方法、StringBuilder

1.String常用方法

1.string
package apiday01;

public class StringDemo {
   public static void main(String[] args) {
       //创建两个对象---一个字面量;另一个是在new String()时创建一个字符串对象
       String s=new String("hello");
       
       String s1="hello";
       //==比较地址
       System.out.println(s==s1);
       //equals比较内容
       System.out.println(s.equals(s1));
  }
}
2.String常用方法(实例方法)
  1. length()

    package apiday01;

    public class LengthDemo {
       public static void main(String[] args) {
           String str="你好中国123";
           int len=str.length();
           System.out.println(len);
      }


    }
  2. toUpperCase()--转大写,toLowerCase()--转小写

    package apiday01;
    /*
    * toUpperCase()转大写
    * toLowerCase()转小写
    * */
    public class ToUpperCaseDemo {
       public static void main(String[] args) {
           String str ="java";
           str=str.toUpperCase();
           System.out.println(str);
      }
    }
  3. trim--去除当前字符串两边的空白字符

    package apiday01;
    /*String trim()
    * 去除当前字符串两边的空白字符
    * */
    public class TrimDemo {
       public static void main(String[] args) {
           String str="   hello   word     ";
           str=str.trim();
           System.out.println(str);
      }
    }
  4. boolean startsWith(String str)---判断当前字符串是否是以给定的字符串开始的

    boolean endsWith()----判断当前字符串是否是以给定的字符串结束的

    package apiday01;
    /*
    boolean startsWith --判断当前字符串是否是以给定的字符串开始的
    boolean endsWith --判断当前字符串是否是以给定的字符串结束的
    * */
    public class StartsWithDemo {
       public static void main(String[] args) {
           String str="hello word";
           boolean a=str.startsWith("hell");
           boolean b=str.endsWith("word");
           System.out.println(a);
           System.out.println(b);
      }
    }
  5. char charAt(int index)---返回当前字符串指定位置上的字符串---根据位置找字符

    package apiday01;
    /*char charAt(int index)
    返回当前字符串指定位置上的字符串---根据位置找字符
    * */
    public class CharAtDemo {
       public static void main(String[] args) {
           String str="thinking in java";
           char c=str.charAt(10);
           System.out.println(c);
      }
    }

     

  6. indexOf(String str) 检索字符在字符串中第一次出现的位置

    package apiday01;
    /*indexOf(String str) 检索字符在字符串中第一次出现的位置
    * */
    public class IndexOfDemo {
       public static void main(String[] args) {
           String str = "thinking in java";
           int index = str.indexOf("in");//检索in在字符串str中第一次出现的位置
           System.out.println(index);//2
           index=str.indexOf("in",3);//从下标为3的位置开始找in的第一次
           System.out.println(index);//5
           index=str.indexOf("IN");//当前字符串不包含IN,所以返回-1
           System.out.println(index);//-1
           
           index=str.lastIndexOf("in");//in最后一次出现的位置
            System.out.println(index);//9
      }}
  7. substring

    package apiday01;
    /*
    * substring(int a.int b)从字符串中截取从下标a开始,到下标b(不包含b)的内容
    * */
    public class SubstringDemo {
       public static void main(String[] args) {
           String str="www.tedu.cn";
           String name=str.substring(3,7);//从第3位开始截取到7范围的字符串
           System.out.println(name);//.ted
           name =str.substring(5);//从第5位开始截取直到末尾
           System.out.println(name);//edu.cn
      }
    }
    5.getName()
    public static void main (String[] args){
       String name1="www.overwatch.com";
       String name2="www.apex.com";
       String name3="www.you.com";
       
       String str1=getName(name1);
       String str2=getName(name2);
       String str3=getName(name3);
     
       System.out.println(str1);
    }
    public String getName(String line){
       int start =line.indexOf(".")+1;
       int end=line.indexOf(".",start);
       return line.substring(start,end);
    }

     

3.String常用方法(静态方法)
  1. static String.valueOf(数据类型a)

    package apiday01;
    /*
    * String.valueOf(),将其他类型变量转换为String类型
    * */
    public class ValueOfDemo {
       public static void main(String[] args) {
           int a=123;
           String s1=String.valueOf(a);//将int类型变量a转换为String类型并赋值给s1
           System.out.println(s1);
           
           double d=123.2434;
           String s2=String.valueOf(d);//将double类型变量d转换为String类型并赋值给s2
           System.out.println(s2);
           
           String s3=a+"";//任何内容和字符串连接的结果都是字符串(效率低)
           System.out.println(s3);
      }
    }

2.StringBuilder

  1. 由于String是不变对象,每次修改内容要创建新对象,因此String不适合做频繁修改操作,Java提供了StringBuilder类

  2. StringBuilder是专门用于修改字符串的一个API,内部维护一个可变的char数组,修改都是在这个数组上进行的,修改速度、性能优秀,并且提供了修改字符串的常见方法:增、删、改、插

    package apiday01;

    public class StringBuilderDemo {
       public static void main(String[] args) {
           String str = "好好学习";
           //复制str的内容
           StringBuilder abc = new StringBuilder(str);
           System.out.println(abc);//好好学习
           //append()追加内容
           abc.append(",为了找份好工作");
           System.out.println(abc);//好好学习,为了找份好工作
           //replace()替换内容
           abc.replace(5, 10, "加油加油");
           System.out.println(abc);//好好学习,加油加油工作
           //delete()删除内容
           abc.delete(0,5);
           System.out.println(abc);//加油加油工作
           //insert()插入内容
           abc.insert(0,"守望先锋");
           System.out.println(abc);//守望先锋加油加油工作
           //reverse()翻转
           abc.reverse();
           System.out.println(abc);//作工油加油加锋先望守
      }
    }





3.getter()\setter()

//point类
public class point{
   private int x;
   private int y;
  public int getX(){
      this.x=x;
  }
   public void setX(){
       return x;
  }
    public int getY(){
      this.y=y;
  }
   public void setY(){
       return y;
  }
}
//SetterGetter类中的main中
Point a=new Point();
a.setX(100,200);
a.setY(629091);
System.out.println(a.getX()+a.getY());

 

2.正则表达式、Object、包装类

1.正则表达式

  1. 正则表达式是用来描述字符串内容格式,使用它通常用来匹配一个字符串的内容是否符合要求

  2. 正则表达式的语法:

    []:表示一个字符,该字符可以是[]中指定的内容
    例如:
    [abc]:这个字符可以是a或b或c
    [a-z]:表示任意一个小写字母
    [a-zA-Z]:表示任意一个字母
    [a-zA-Z0-9_]:表示任意一个数字字母下划线
    [^abc]:该字符只要不是a或b或c

    预定义字符:
    .:表示任意一个字符,没有范围限制
    \d:表示任意一个数字,等同于[0-9]
    \w:表示任意一个单词字符,等同于[a-zA-Z0-9_]
    \s:表示任意一个空白字符
    \D:表示不是数字
    \W:不是单词字符
    \S:不是空白字符

    量词:
    ?:表示前面的内容出现0-1
     例如: [abc]? 可以匹配:a b c 或什么也不写
    +:表示前面的内容最少出现1次
     例如: [abc]+ 可以匹配:b或aaaaaaaaaa...或abcabcbabcbabcbabcbabbabab....
           但是不能匹配:什么都不写 abcfdfsbbaqbb34bbwer...
    *:表示前面的内容出现任意次(0-多次)---匹配内容与+一致,只是可以一次都不写
     例如: [abc]* 可以匹配:b或aaaaaaaaaa...或abcabcbabcbabcbabcbabbabab....或什么也不写
           但是不能匹配:abcfdfsbbaqbb34bbwer...
    {n}:表示前面的内容出现n次
     例如: [abc]{3} 可以匹配:aaa bbb aab 或abc 或bbc
           但是不能匹配: aaaa aad
    {n,m}:表示前面的内容出现最少n次最多m次
     例如: [abc]{3,5} 可以匹配:aaa 或  abcab 或者 abcc
           但是不能匹配:aaaaaa aabbd
    {n,}:表示前面的内容出现n次以上(含n次)
     例如: [abc]{3,} 可以匹配:aaa aaaaa.... abcbabbcbabcbabcba....
           但是不能匹配:aa abbdaw...
    ()用于分组,是将括号内的内容看做是一个整体
     例如: (abc){3} 表示abc整体出现3次. 可以匹配abcabcabc
           但是不能匹配aaa 或abcabc
          (abc|def){3}表示abc或def整体出现3次.
           可以匹配: abcabcabc defdefdef abcdefabc
           但是不能匹配abcdef 或abcdfbdef

  3. String支持与正则表达式相关的方法:

    • matches():使用给定的正则表达式验证当前字符串的格式是否符合要求

      package apiday02;
      /*邮箱的正确表达式
         [a-zA-Z0-9_]+@[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)+
      * */
      public class MatchesDemo {
         public static void main(String[] args) {
             String email = "936572339@qq.com";
             String regex = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";
             boolean match = email.matches(regex);
             if (match) {
                 System.out.println("是正确的邮箱");
            } else {
                 System.out.println("不是正确的邮箱");
            }
        }
      }

       

    • split():将当前字符串按照满足正则表达式的部分进行拆分

      package apiday02;

      import java.util.Arrays;

      public class SplitDemo {
         public static void main(String[] args) {
             String line="abc123def456ghi";
             String[] data=line.split("[0-9]+");
             System.out.println(Arrays.toString(data));//[abc, def, ghi]


             line="123.456.7898";
             data=line.split("\\.");
             System.out.println(Arrays.toString(data));//[123, 456, 7898]


             line="123,456,789";
             data=line.split(",");
             System.out.println(Arrays.toString(data));//[123, 456, 789]

             //最开始就是可拆分项(.),那么数组中的第一个元素为空字符串;
             //如果连续两个(两个以上)可拆分项,他们中间也会被拆出一个空字符串;
             //如果末尾连续多个可拆分项,那么拆出的空字符串被忽略
             line=".123.456..789.11.11111.......";
             data=line.split("\\.");
             System.out.println(Arrays.toString(data));//[, 123, 456, , 789, 11, 11111]



        }
      }
    • replaceAll():将当前字符串中满足正则表达式的部分替换为给定的字符串

      package apiday02;

      public class ReplaceAllDemo {
         public static void main(String[] args) {
             String line="abc123sss345ewww";
             line=line.replaceAll("[a-z]+","xiaoyezi");
             System.out.println(line);//xiaoyezi123xiaoyezi345xiaoyezi
        }
      }

       

2.Object

  • 是所有类的鼻祖,所有类都直接或间接继承了Object,万物皆对象,为了多态

  • 里面有几个经常被派生类重写的方法: toString()和equals()

    • 调用toString()时默认返回: 类的全称@地址,没有参考意义,所以常常重写toString()返回具体数据

    • 调用equals()时默认比较的还是==(即比较地址),没有参考意义,所以常常重写equals()来比较具体的属性值

    • 派生类重写equals()的基本规则:

      1. 两个对象必须是同一类型,若类型不同则返回false

      2. 若参数对象为null,则返回false

      3. 原则上两个对象要比较对象的属性是否相同

3.包装类

  1. Java定义了8个包装类,目的是为了解决基本类型不能直接参与面向对象开发的问题,使得基本类型可以通过包装类的实例以对象的方式存在

  2. 包括:Integer、Character、Byte、Short、Long、Float、Double、Boolean。其中Character和Boolean是直接继承自Object的,而其余6个包装类都继承自java.lang.Number

  3. JDK1.5推出了一个新的特性:自动拆装箱,该特性是编译器认可,当编译器编译时若发现有基本类型与包装类型相互赋值时,将会自动补充代码来完成他们的转换工作,这个过程为自动拆装箱

  4. package apiday02;

    public class IntegerDemo {
       public static void main(String[] args) {
           //2)包装类可以将字符串转换为对应的基本类型---前提是该字符串正确表达了基本类型的值;若不能正确表达,则发生NumberFormatException数字转换异常
           String str="123";
           int num=Integer.parseInt(str);
           System.out.println(num);//123
            String str1="123.456";
           double num1=Double.parseDouble(str1);
           System.out.println(num1);//123.456



           //1)可以通过包装类来得到基本类型的取值范围:
           int max=Integer.MAX_VALUE;
           int min =Integer.MIN_VALUE;
           System.out.println("int的最大值为:"+max+",int的最小值为:"+min);

           long lMax=Long.MAX_VALUE;
           long lMin=Long.MIN_VALUE;
           System.out.println("long的最大值为:"+lMax+",long的最小值为:"+lMin);
          /** //自动拆装箱
           //下列代码会被编译为:Integer i1=Integer.valueOf(5)
           Integer i1=5;
           //int i2=i1.int.valueOf()
           int i2=i1;
           System.out.println(i1+","+i2);*/
      }
    }

4.二进制

1.2进制

  1. 逢二进一的计数规则

  2. 如何将2进制转换为10进制?

    • 将一个2进制数每个1位置的权值累加即可

  3. Java 所有的变量\常量存储的都是2进制数

  4. 代码

    public class Demo01 {
       public static void main(String[] args) {
           /*
            1.java在编译期间将10进制数编译为2进制数,按2进制来运算
                .java(50) 编译后 .class(110010)
            2.Integer.toBinaryString()可以将底层的2进制数显示出来
            3.int类型是32位2进制数,显示2进制数时自动省略高位0
            4.System.out.println()将2进制转换为10进制输出
            */
           int n = 50; //110010
           System.out.println(Integer.toBinaryString(n)); //2进制
           n++; //110011
           System.out.println(n); //10进制
           System.out.println(Integer.toBinaryString(n)); //2进制
      }
    }

2.16进制

  1. 逢16进1的计数规则

  2. 16进制来缩写2进制数字

  3. 缩写: 将2进制从最低位开始,每4位2进制缩写为1位16进制

  4. public class Demo02 {
       public static void main(String[] args) {
           /*
             16进制:缩写2进制
              1)0x是16进制字面量前缀,0x开头则编译器按照16进制编译
              2)Java 7提供了2进制字面量前缀 0b----不用,一般都用16进制
            */
           int n = 0x4f057afe; //0x表示16进制
           int m = 0b1001111000001010111101011111110; //0b表示二进制
           System.out.println(Integer.toBinaryString(n)); //按2进制输出
           System.out.println(Integer.toBinaryString(m)); //按2进制输出
           //结论:用16进制来表示2进制更方便

           /*
            8进制:
            1)逢8进1的计数规则
            2)前缀0表示为8进制
            3)数字:0,1,2,3,4,5,6,7,没有7以上的数字
            */
           //----小面试题(8进制平时不用)
           //权     64 8 1
           int x =  067; //0开头表示8进制
           System.out.println(x); //十进制的55(6个8加上7个1)

      }
    }

3.补码

  1. 计算机中处理有符号数(正负数)的一种编码方式,java中的补码最小类型是int,32位数

  2. 以4位2进制为例讲解补码的编码规则:

    • 计算的时候如果超出4位数就自动溢出舍弃,保持4位数不变

    • 将4位2进制数分一半作为负数使用

    • 最高位称为符号位,高位为1是负数,高位为0是正数

      int n = -3;
      System.out.println(Integer.toBinaryString(n));

      /*
      规律数:
      1)0111为4位补码的最大值,规律是1个0和3个1,可以推导出:
       32位补码的最大值,是1个0和31个1-----(011111111...)
      2)1000为4位补码的最小值,规律是1个1和3个0,可以推导出:
       32位补码的最小值,是1个1和31个0-----(100000000...)
      3)1111为4位补码的-1,规律是4个1,可以推导出:
       32位补码的-1是,是32个1------------(11111111...)
      */    
      int max = 2147483647; //int的最大值
      int min = -2147483648; //int的最小值
      System.out.println(Integer.toBinaryString(max)); //011111...
      System.out.println(Integer.toBinaryString(min)); //100000...
      System.out.println(Integer.toBinaryString(-1)); //11111...

  3. 深入理解负值:

    • 记住-1的编码是32个1

    • 用-1减去0位置对应的权值

  4. 互补对称:

     

    • 公式:-n=~n+1 结论:一个数的补码=这个数取反+1

    • 代码

      int n = -3;int m = ~n+1;System.out.println(m); //3  -3的补码就是-3取

       

  5. 位运算:

    • ~:取反(0变1、1变0)

    • &:与运算(有0则0)

    • |:或运算(有1则1)

    • “>>>”:右移位运算

    • <<:左移位运算

posted @ 2022-03-27 20:21  约拿小叶  阅读(78)  评论(0编辑  收藏  举报