Java基础01

无论多么艰难,都要继续前进,因为只有你放弃的那一刻,你才输了。 

一、学前预备知识

1.常见cmd命令

1.盘符名称+冒号

  • 说明:盘符切换
  • 举例:E: 回车,表示切换到E盘
  • 2.dir
  • 说明:查看当前路径下的内容(包括隐藏内容)
  • 3.cd目录
  • 说明:进入单级目录
  • 举例:cd 爱奇艺
  • 4.cd..
  • 说明:回退到上一级
  1. 5.cd 目录1\目录2\...
  2. 说明:进入多级目录
  3. 举例:cd 爱奇艺\电视剧
  4. 6.cd \
  5. 说明:回退到盘符目录
  6. 7.cls
  7. 说明:清屏
  8. 8.exit
  9. 说明:退出命令提示符窗口。

2.软件下载即配置

1.JDK目录

要着重bin目录

2.环境配置

JDK所配置的环境,仅包含了四个工具,所以要自己进行配置

1.先删掉jdk配置的环境

2.先配置JAVA_HOME。(路径不带bin)

3.再配置Path.(%IAVA_HOME%\bin)

二、基础

1.基础知识

JAVA SE JAVA语言的标准版,用于桌面应用的开发,是其他两个版本的基础。

JAVA ME  java语言的小型版,用于嵌入式电子设备或者小型一定设备,现在不常用。

JAVA EE  java语言的企业版,用于Web方向的网站开发。网站开发:浏览器+服务器

JAVA的主要特性:

1.面向对象 2.跨平台 3.开源 4.简单易用 5.多线程 6.安全性

java是混合型的编译运行方式

JAVA语言的跨平台是通过虚拟机实现的

JAVA语言不是直接运行在操作系统里边的。而是运行在虚拟机中的。

针对不同的操作系统,安装不同的虚拟机就可以。

JDK(java  development kit):java开发工具包 包括:

  • JVM(java virtual machine):java虚拟机,真正运行JAVA程序的地方
  • 核心类库:java已经写好的东西,我们可以直接用
  • 开发工具  javac 编译工具  java运行工具 jdb 调试工具….

JRE(java runtime environment):JAVA的运行环境

  • JVM(java virtual machine):java虚拟机,真正运行JAVA程序的地方
  • 核心类库:java已经定义好的库
  • 运行工具

2.基础概念

1.注释:

idea中的快捷键是ctrl+shift+/

  • 单行注释  //
  • 多行注释   /**/
  • 文档注释

 注释使用细节:

  • 注释内容不会参与编译和运行,仅仅是对代码的解释说明
  • 不管是单行注释还是多行注释,在书写的时候都不要嵌套

2.关键字:被JAVA赋予了特定涵义的英文单词

 关键字特点:

  • 关键字的字母全部小写
  • 常用的代码编辑器,针对关键字有特殊颜色标记

class:用于创建/定义一个类,后面跟随类名

3.字面量:数据在程序中的书写格式

   分类:

字面量类型

说明

举例

整数类型

不带小数点的数字

666,-88

小数类型

带小数点的数字

13.14 -13.12

字符串类型

双引号括起来的内容

“Hello World”,"程序"

字符类型

单引号括起来的内容,内容只能有一个

'A','0','我'

布尔类型

布尔值,表示真假

只有两个值:true,false

空类型

一个特殊的值,空值

NULL“NULL”不能直接打印,只能以字符串的形式打印

    特殊字符:

\t  制表符 在打印的时候,把前面字符串的长度补齐8,或者8的整数倍。最少补1个空格,最多补8个空格。(可以让打印的数据对齐)

4.变量:在程序执行过程中,值可能会发生改变的量

变量的定义格式

数据类型 变量名=数据值;

变量的注意事项

1.只能存一个值

2.变量名不允许重复定义

3.一条语句可以定义多个变量

4.变量在使用之前一定要进行赋值

5.变量的作用域范围

5.计算机的存储规则

  1.txt文本--数字 转二进制存储--字母、汉字 查询码表

 2.Image图片--每一个像素点的RGB三原色来存储

 3.Sound声音--对声音的波形图进行采样再存储

 6. 数据类型

  1.基本数据类型

  • 如果要定义long类型的变量  在数据值的后面需要加一个L作为后缀,L可以是大写也可以是小写,推荐大写。
long n=99999L;
  • 如果要定义float类型的变量  在数据值的后面需要加一个F作为后缀,F可以是大写也可以是小写,推荐大写。
float f=10.1f;
  •  double类型不用加后缀。
  • 布尔类型:
  • boolean o=true;
  • 整数和小数取值范围大小关系:
double>float>long>int>short>byte

   2.引用数据类型

标识符:给类、方法、变量等起的名字

标识符命名规则--硬性要求

    由数字、字母、下划线(_)和美元符($)组成

3.IDEA下载使用

IDEA项目结构介绍

1.project 项目

2.module 模块

3.package 包

4.class 类

Eg:

微信看做 项目

下方 消息、通讯录、发现、我 可以看做四个独立的模块

以消息为例:

IDEA中的代码:

缩写:
psvm:
public static void main(String [] args){
}

sout:
System.out.println();




输出语句:

System.out.println("abc");//先打印abc再进行换行
System.out.print("abc");//只打印abc,不换行
System.out.println();//不打印任何数据,只做换行处理

 System.out.printf("%s你好","张三");//用后边的字符串来填补%s,不能自动换行,输出:张三你好
 System.out.printf("%s你好%s","张三","李四");//输出张三你好李四

关于类的操作:

1.删除类:右键,delete

2.新创建类

3.修改类名:右键,refector,rename

关于模块:

1.新建

2.删除

3.修改

4.导入

三、语法

1.运算符

算术运算符

+ - * / %

  • 有小数参与运算时,结果有可能不精确
  • 整数参与运算,结果只能是整数
  • 想要得到小数,要有小数参与运算

 高级用法

  • 数字相加

数据类型不一致,需要转成一致的才能参与运算

类型转换的分类

1.隐式转换--(自动的

  • 取值范围小的转换成取值范围
  • Byte、short、char三种类型的数据在运算时,都会直接先提升为int,然后再进行运算

2.强制转换

  • 把取值范围大的数值,赋值给取值范围小的数值
  • 格式: 目标数据类型 变量名=(目标数据类型)被强转的数据
  • 字符串的“+”操作
    • 当“+”操作中出现字符串时,,这个“+”是字符串连接符,而不是算术运算符了。会将前后的数据进行拼接并产生一个新的字符串

  • 连续进行“+”操作时,从左到右逐个执行

  • 字符相加
    • 字符+字符或者是字符+数字时,会把字符通过ASCLL码表查询到对应的数字再进行计算。

自增自减运算符

  • ++、--
  • ++ 、--无论放在变量前边还是放在后边,单独放一行,结果一样。
  • A++ ,先用后加   ++a, 先加后用

赋值运算符

  • =   赋值 
  • +=  加后赋值  a+=b,将a+b的值给a
  • -=  减后赋值  a-=b,将a-b的值给a
  • *=  乘后赋值  a*=b,将a*b的值给a
  • /= 除后赋值   a/=b,将a/b的商给a
  • %=  取余后赋值  a%=b,将a/b的余数给a
  • += -=  *=  /=  %=底层都隐藏了一个强制类型转换

关系运算符

  • 关系运算符的结果都是boolean类型
import java.util.Scanner;

public class base {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int me=sc.nextInt();
        int girl=sc.nextInt();
        boolean result=me>girl;
        System.out.println(result);
    }

}

逻辑运算符

  • & 逻辑与(且)---两边都满足
  • |   逻辑或  ----两边满足一个
  • ^ 逻辑异或-----同为false,不同为true
  • !逻辑非-----取反

短路逻辑运算符

  • &&  短路与---结果与单个&一样,但是具有短路效果,当左边的表达式的值可以确定最终的结果,右边就不会参与运算。
  •  ||   短路或-----结果与|一样,但是具有短路效果,当左边的表达式的值可以确定最终的结果,右边就不会参与运算。
  • 注意事项:
    • & |,无论左边true false,右边都要执行。
    • && ||,如果左边能确定整个表达式的结果,右边不执行。
    • &&:左边为false ,右边不管是真是假,整个表达式的结果一定是false。
    • ||:左边为true,右边不管是真是假,整个表达式的结果一定是true。
    • 这两种情况,右边不执行,提高了效率

三元运算符:可以进行判断,根据判断的内容来选择不同的结果

  • 格式:关系表达式? 表达式1:表达式2
  • 如果关系表达式的值为真,则输出表达式1的值,否则输出表达式2的值。
  • 三元运算符的值必须要使用

运算符优先级

  • ()最高

2.判断和循环

流程控制语句

  • 顺序结构
  • 判断语句

    • If  格式:

      • 第一种格式
if(关系表达式){
    语句体;
}

注意点:

1.大括号的开头可以另起一行书写,但最规范的是写在第一行的末尾

2.在语句体中,如果只有一句代码,大括号可以不写

3.如果对一个布尔类型的变量进行判断,可以不用写==

  •                   第二种格式:
if(关系表达式){
        语句体;
    }
    else{
        语句体2;
    }
  •                 第三种格式:
       if(关系表达式1){
            语句体;
        }
        else if(关系表达式2){
            语句体2;
        }
        else{
            语句体n;
        }
  • Switch

       switch(表达式){
                case 1:
                    语句体1;
                    break;
                case 2:
                    语句体2;
                    break;
                ...
                default:
                    语句体n;
                    break;
    
            }
    • default的位置和省略
      • default可以省略,语法不会有问题,但是不建议省略
      • default可以写在任何位置,但是习惯写在最下边
    • Case 穿透---语句体当中没有写break;
      • 执行后没有遇到break,就不会结束整个switch,会继续往下穿透,直到遇到break或者是大括号
    • switch的新特性
      • Jdk12后才有
 switch(表达式){
            case 1->{
                //语句体1;
            }
            case 2->{
                //语句2;
            }
               
            ...
            default->{
               语句3;
            }
        }
  • 当每个case语句 中只用执行一句话时可以用
 switch(表达式){
            case 1-> System.out.println("1");
            case 2-> System.out.println("2");
            ...
            default-> System.out.println("3");
        }
  • 再结合case的穿透性

 switch(表达式){
            case 1,2-> System.out.println("2");
            ...
            default-> System.out.println("3");
        }
  • 循环语句

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

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

  • for和while的区别
    • for循环中,控制循环的变量,因为归属for循环的语法结构中,在for循环结束后,就不能再次被访问到了。
    • while循环中,控制循环的变量,对于while循环来说不归属其语法结构中,在while循环结束后,改变量还可以继续使用。
  • do ...while

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

语句体

}while(true);


for(;;){
语句体
            
}


 while(true){
语句体
            
 }
  • 跳转控制语句
    • Continue 结束本次循环,继续下次循环
    • Break  结束整个循环

3.数组

数组指的是一种容器,可以用来存储同种数据类型的多个值

数组容器在存储数据的时候,需要结合隐式转换考虑

数组的定义

格式1:
数据类型[] 数组名
 int [] array;

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

数组的初始化

  • 静态初始化

格式:

完整格式:
数据类型 [] 数组名= new 数据类型[] {};

简化格式:
数据类型 [] 数组名={};
int [] array1=new int[]{11,12,13,14};
     int []array2={11 , 12,13,15};
     String []array3=new String[]{"xioaming","xioahong"};
     String []array4={"xioaming","xioahong"};

数组名为数组的地址值

public static void main(String[] args) {
        System.out.println("hello world");
        int []arr={1,2,3,4,5};
        System.out.println(arr);//[I@6f496d9f
      
    }

1.[:表示当前是一个数组

2.I:表示当前数组里面的元素都是int类型的

3.@:表示一个间隔符号(固定格式)

4.后边的才是数组真正的地址

动态数组

数据类型 [] 数组名=new 数据类型[数组长度];

数组默认初始化值的规律

1.整数类型:默认初始化为0

2.小数类型:默认初始化0.0

3.字符类型:默认初始化值'/u0000'空格

4.布尔类型:默认false

5.引用数据类型:默认NULL

四、java内存分配

1.方法运行使用的内存,比如main()方法运行时,进入方法栈中执行

2.:存储对象或者数组,new创建出的对象都存储在堆内存

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

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

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

总结:

1.只要是new出来的都在堆里面开辟了一个小空间

2.如果new了多次,那么在堆里面有多个小空间,每个小空间中都有各自的数据

总结:当两个数字指向同一个小空间时,其中一个数组对小空间中的值发生了改变,那么其他数组再次访问的时候都是修改之后的结果了。

五、方法:是程序中最小的执行单元

 重复的代码、具有独立功能的代码可以抽取到方法中

方法的好处:

1.提高代码的复用性2.提高代码的可维护性

方法的作用:把一些代码打包在一起,用到的时候就调用

1.方法定义

方法必须先定义后调用

public static 返回值类型  方法名(参数){

    方法体;
    return 返回值;
}

形参:全称形式参数,是指方法定义中的参数

实参:全称实际参数,方法调用中的参数

注:方法调用时,参数的数量与类型必须与方法定义中小括号里面的变量一一对应,否则程序将报错。

方法定义的小技巧:

        1.我要干什么?-----方法体

        2.我干这件事情需要什么才能完成?------形参

2.方法调用

方法注意事项

1.方法不调用就不执行

2.方法与方法之间是平级关系,不能互相嵌套定义

3.方法的编写顺序和执行顺序无关

4.方法的返回值类型为void,表示该方法没有返回值,如果返回值的方法可以省略return语句不写。如果要编写return,后面不能跟具体的数据

5.return语句下面,不能编写代码,因为永远执行不到,属于无效代码

3.方法重载:在同一个类中,方法名相同,参数不同的方法。与返回值无关

参数顺序不同可以构成重载,但是不建议

基本数据类型:变量里存储的是真实的数据

引用数据类型:new出来的都是引用数据类型,变量中存储的是地址值。引用:使用其他空间的数据

练习:

1.产生验证码

import java.util.Random;

/*需求:
定义方法实现随机产生一个5位的验证码
验证码格式:
长度为5
前四位是大写或小写字母
最后一位是数字
* */
public class hellowworld {
    public static void main(String[] args) {
        verificationCode();
    }

    public static void verificationCode() {
        //1.将小写字母和大写字母存数组中
        char []vc=new char[52];
        for(int i=0;i<vc.length;i++){
            if(i<=25){
                vc[i]=(char)(97+i);//存小写字母
            }else {//存大写字母
                vc[i] = (char) (((int) ('A')) + i - 26);
            }
        }
        //定义字符串
        String code="";
        //2.随机取四个字母
        Random r=new Random();
        for(int j=0;j<4;j++){
            int randomIndex=r.nextInt(vc.length);
            code=code+vc[randomIndex];
        }
        //3.随机取一个数字
        int number=r.nextInt(10);
        code=code+number;
        System.out.println(code);

    }

}

2.加密解密

import java.util.Scanner;
/*需求:
某系统的数字密码(大于0)比如1983,采用加密方式进行传输,
规则如下:
每位数加上5,在对10求余
最后将所有数字反转,得到一串新数
* */
public class hellowworld {
    public static void main(String[] args) {
        digitalEncryption();

    }

    public static void digitalEncryption() {
        Scanner sc = new Scanner(System.in);
        int password = sc.nextInt();
        int copy = password, code= 0;

        while (copy % 10 != 0) {
           int num = copy % 10;
            code = ((num + 5) % 10) +code* 10;
            copy = copy / 10;
        }
        System.out.println(code);
    }


}

六、二维数组:

数组中存数组

1.二维数组的初始化

静态初始化:

数据类型 [][]数组名=new 数据类型[][]{{元素1,元素2},{元素1,元素2}};
eg:
 int [][]arr=new int[][]{{1,2},{3,4}};
简化格式:数据类型[][]数组名={{元素1,元素2},{元素1,元素2}};
eg:
int [][]arr={{11,22},{33,44}};//符合阿里巴巴代码规范
int arr[][]={{11,22},{33,44}};//也可以,但不推荐
//建议这样定义,把每一个一维数组,单独写一行
//注意:每一个一维数组其实是二维数组中的元素,
//所以每一个一维数组之间需要用逗号隔开,最后一个一维数组后面不需要加逗号
int [][]arr={
                {1,2},
                {3,4}
        };



//二维数组的遍历
        int [][]arr={
                {1,2,8},
                {3,4,9}
        };
        //外循环:遍历二维数组,得到里边的每一个一维数组
        for(int i=0;i< arr.length;i++){
            //内循环:遍历一维数组,得到里面的每一个元素
            for(int j=0;j<arr[i].length;j++){
                System.out.print(arr[i][j]+" ");
            }
            System.out.println();
        }
    

二维数组的动态初始化

数据类型 [][]数组名=new 数据类型[m][n];
  m表示这个二维数组,可以存放多少个一维数组,n表示每一一维数组,可以存放多少个元素
eg:
        
  int [][]arr=new int[2][3];

二维数组的内存图

 特殊情况1:初始:

 赋值后:

七、面向对象

设计对象并使用

1.类和对象

类:是对像共同特征的描述

对象:是真是存在的具体东西

在java中,必须先设计类,才能获得对象

如何定义类

定义类:
    public class 类名{
        1.成员变量(代表属性,一般是名词)
        2.成员方法(代表行为,一般是动词)
        3.构造器
        4.代码块
        5.内部类
    }

得到类对象:
类名 对象名=new 类名();

使用方法:

访问属性:
对象名.成员变量
访问行为:
对象名。方法名(...)

eg:
public class Phone {

       //属性(成员变量)
        String brand;
        double prices;
        //行为(方法)
        public void call(){
            System.out.println("手机在打电话");

        }
        public void playGame(){
            System.out.println("手机在玩游戏");

        }


}
//测试类
public class PhoneTest {
    //创建对象
    public static void main(String[] args) {
        Phone p=new Phone();
        p.brand="小米";
        p.prices=199.86;
        System.out.println(p.brand);
        System.out.println(p.prices);
        p.playGame();
        p.call();
    }

}

类的几个补充注意事项

1.用来描述一类事物的类,专业叫做:Javabean类

在Javabean类中,不写main方法。

2.编写main方法的类,叫做测试类

我们可以在测试类中创建javabean类的对象并进行赋值调用。

3.类名首字母建议大写,需要见名知义,驼峰模式

4.一个java文件可以定义多个class类,且只能一个类时public修饰,而且public修饰的类名必须成为代码文件名。实际开发中建议还是一个文件定义一个class类

5.成员变量的完整定义格式是 修饰符 数据类型 变量名称 =初始化值;一般无需指定初始化值,存在默认值。

对象的成员变量的默认值规则:

 开发中类的设计

可以提取名词--》属性

可以提取动词--》行为

2.封装

告诉我们:如何正确设计对象的属性和方法。

原则:对象代表什么,就得封装对应的数据,并提供数据对应的行为

eg: 人关门

关门这个方法是门的方法。

private关键字

  • 是一个权限修饰符
  • 可以修饰成员(成员变量和成员方法)
  • 被private修饰的成员只能在本类中才能访问
  • 针对private修饰的成员变量,如果需要被其他类使用,必须提供相应的操作
  • 提供“setXxx(参数)”方法,用于给成员变量赋值,方法用public修饰
  • 提供“getXxx()”方法,用于获取成员变量的值,方法用public修饰
public class girlFriend {
    private String name;
    private int age;


    //针对每一个私有化的成员变量,都要提供get和set方法
    //name
    public void setName(String name) {
        this.name = name;
    }
    public String getName(){
        return name;
    }

    //age
    public void setAge(int age){
        if(age>0&&age<=100)
            this.age=age;
        else
            System.out.println("非法输入");
    }
    public int getAge(){

        return age;
    }

    public void sleep(){
        System.out.println("女朋友在睡觉");
    }
}


//测试类
public class girlFriendTest {
    public static void main(String[] args) {
        girlFriend gf=new girlFriend();
        gf.setName("Сʫʫ");
        gf.setAge(-1);
        System.out.println(gf.getName());
        System.out.println(gf.getAge());
        gf.sleep();

    }
}

局部变量和成员变量

局部变量和成员变量重名是按照就近原则,要用成员变量就用 “this. +成员变量”

this的作用:区别成员变量和局部变量

3.构造方法

也叫构造器、构造函数

作用:在创建对象的时候,由虚拟机自动调用,给成员变量进行初始化

构造方法有:

1.无参数构造方法:初始化对象时,成员变量的数据均采用默认值

2.有参数构造方法:初始化对象时,同时给成员变量赋值

格式:

  修饰符 类名(参数){
        方法体;
  }

特点:

1.方法名与类名相同,大小写也要一致

2.没有返回值类型,连void也没有

3.没有具体的返回值(不能由return带回结果数据)

执行时机:

1.创建对象的时候由虚拟机调用,不能手动调用构造方法

2.每创建一次对象,就会调用一次构造方法

 构造方法注意事项:

1.构造方法的定义:

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

2.构造方法的重载

  • 带参构造方法,和无参数构造方法,两者方法名相同,但是参数不同,这叫构造方法的重载

3.推荐使用方法

  • 无论是否使用,都手动书写无参数构造方法,和带全部参数的构造方法

八、标准的JavaBean

  1. 类名需要见名知意,驼峰命名
  2. 成员变量使用private修饰
  3. 至少提供两个构造方法
    1. 无参构造方法
    2. 带全部参数的构造方法
  4. 成员方法
    1. 提供每个成员变量对应的setX()/getX()
    2. 如果还有其他行为,也需要写上
package test01;

public class girlFriend {
    private String name;
    private String password;
    private int age;
//无参构造方法

    public girlFriend() {
    }
//有全部参数的构造方法

    public girlFriend(String name, String password, int age) {
        this.name = name;
        this.password = password;
        this.age = age;
    }
//name

    public String getName() {
        return name;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
//age
    public int getAge() {
        return age;
    }

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

对象内存图

 

一个对象的内存图: 

 在study()方法使用完后,study方法出栈,程序结束,main()方法也出栈,之后堆内存中会被回收

 两个对象的内存图

  两个引用指向同一个对象:当两个引用其中一个对这个对象的内容进行改变后,另一个引用再次访问时,就是改变后的值。

 stu1=NULL:

 基本数据类型和引用数据类型

基本数据类型:数据值是存储在自己的空间中

特点:赋值给其他变量,赋的真实的值

引用数据类型:数据值是存储在其他空间中,子集空间中存储的是地址值

特点:赋值给其他变量,赋的是地址

this的内存原理:

this的本质:代表方法调用者的地址值

成员变量和局部变量

成员变量:类中方法外的变量

局部变量:方法中的变量

 

九、API与字符串

API(Application Programming Interface):应用程序编程接口

简单理解:API就是别人已经写好的东西,我们不需要自己编写,直接使用即可。

java API :指的就是jdk中提供的各种功能的java类

这些类将底层的实现封装了起来,我们不需要关心这些类时如何实现的,只需要学习这些类如何使用即可

API帮助文档:帮助开发人员更好使用和查询API的一个工具

使用方法:

1.打开API帮助文档

2.点击显示,并找到索引下面的输入

3.在输入框中输入类名并点击显示

4.查看类所在的包

5.查看类的描述

6.查看构造方法

7.查看成员方法

字符串

1.java.lang.String类代表字符串,java程序中的所有字符串文字都为此类的对象。

使用时不用导包。

2.字符串的内容是不会发生改变的,它的对象在创建后不能被更改。

 String name="哈哈";
 name="你好";
 System.out.println(name);
//实际创建了两个对象


 String name="哈哈";
 dongzuo="你好";
 System.out.println(name+dongzuo);
/实际创建了三个对象

  构造方法

1.直接赋值

//直接赋值方式获得一个字符串对象(用的最多)
        String s1 = "abc";
        System.out.println(s1);//abc

2.new

//使用new的方式来获取一个字符串对象(相当于“”)
        String s2=new String();
        System.out.println("你好"+s2+"不好");//你好不好

        //传递一个字符串,根据传递的字符串内容再创建一个新的字符串对象(很少使用)
        String s3=new String("abcd");//abcd
        System.out.println(s3);

        //传递一个字符数组,根据字符数组的内容再创建一个新的字符串对象
        //需求:修改字符串内容
        //abc--->{'a','b','c'}---->{'Q','b','c'}----->"Qbc"
        char []chs={'a','b','c'};
        String s4=new String(chs);//abc
        System.out.println(s4);

        //传递一个字节数组,根据字节数组的内容再创建一个新的字符串对象
        //应用场景:以后在网络当中传输的数据其实都是字节信息
        //我们一般要把字节信息进行转换,转成字符串,此时就要用到这个构造了
        byte[] bytes={97,98,99};
        String s5=new String(bytes);
        System.out.println(s5);//abc

内存模型:String Table(串池)在jdk7版本开始从方法区挪到了堆内存

直接赋值:--节约内存-代码最简单

当使用双引号直接赋值时,系统会检查该字符串在串池中是否存在。不存在:创建新的;存在:复用。

 用new创建字符串对象:

常用方法:

 1.比较

 ==号比的到底是什么?

 

 字符串比较--比较内容

        String s1 = "abc";
        String s2 = new String("abc");
//==号比较
        System.out.println(s1 == s2);//false
//比较字符串对象中的内容是否相同
        boolean result1 = s1.equals(s2);
        System.out.println(result1);//true


        String s3 = new String("Abc");

        boolean result2 = s1.equals(s3);
        System.out.println(result2);//false

        boolean result3 = s1.equalsIgnoreCase(s3);
        System.out.println(result3);//true

结论:
      以后只要想比较字符串的内容,就必须要用String里面的方法 

练习:

 //1.键盘录入一个abc
        Scanner sc=new Scanner(System.in);
        String s1=sc.next();//abc  是new出来的
        //2.代码中在定义一个字符串abc
        String s2="abc";
        //3.用==比较,这两者能一样吗?
        System.out.println(s1==s2);//false
        
        //结论:
        //以后只要想比较字符串的内容,就必须要用String里面的方法

录入一个字符串,并遍历 

    //键盘录入一个字符串,并遍历
        Scanner sc=new Scanner(System.in);
        String s=sc.next();

        for(int i=0;i<s.length();i++){
            char c=s.charAt(i);
            System.out.print(c+" ");
        }

金额转换:

    public static void main(String[] args) {
        //1.键盘录入一个金额
        Scanner sc=new Scanner(System.in);
        int money;
        while(true){

            System.out.println("请录入一个金额:");
            money=sc.nextInt();
            if(money>=0&&money<=9999999){
                break;
            }
            else{
                System.out.println("金额无效!");
            }
        }
        //定义一个变量用来表示钱的大写
        String moneyStr=MoneyStr(money);
        System.out.println(moneyStr);


    }

    //对money进行变换
    public static String MoneyStr(int money) {
        String []CapitalNumber={"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
        String []DanWei={"佰","拾","万","仟","佰","拾","元"};
        String moneyStr="";
        //2.得到money里面每一位数字,再转成中文
        while(money!=0){
            int ge=money%10;
            moneyStr=CapitalNumber[ge]+moneyStr;
            money=money/10;
        }
        //3.补齐七位数
        int cout=7-moneyStr.length();
        for(int i=0;i<cout;i++){
            moneyStr="零"+moneyStr;
        }

        String result="";//最终结果
        //4.插入单位
        for(int i=0;i<moneyStr.length();i++){
            char c=moneyStr.charAt(i);
           result=result+c+DanWei[i];
        }
        return  result;
    }
  • String substring(int beginindex,int endindex)   截取
    • 注意点:包头不包尾,包左不包右。只有返回值才是截取的小串。
  • String substring(int beginindex)  截取到末尾
  • charAt()   返回一个字符串的指定位置的字符,索引是从[0,length-1].比如:
    • str.charAt(0)检索str中的第一个字符,str.charAt(str.length()-1)检索最后一个字符。

        //从身份证中获取信息
        String id="41138120060510302X";
        String year=id.substring(6,10);
        String month=id.substring(10,12);
        String day=id.substring(12,14);
        System.out.println("人物信息为:");
        System.out.println("出生年月日:"+year+"年"+month+"月"+day+"日");
        //获取性别
        char gender=id.charAt(16);//'3'
        int num=gender-48;
        if(num%2==0){
            System.out.println("性别为:女");
        }else{
            System.out.println("性别为:男");
        }

  • String.replace(char oldchar,char newchar) 替换
     String num = "1,2,3";
        String[] arr = {"1","2","4"};
        for(int i=0;i<arr.length;i++){
            num=num.replace(arr[i],"*");
        }

        System.out.println(num);

十、StringBuilder和StringJoiner概述

StringBuilder概述

使用场景:

1.字符串的拼接

2.字符串的反转

StringBuilder 可以看成是一个容器,创建之后里面的内容是可变的

  •         作用:提高字符串的操作效率

构造方法:

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

StringBuilder常用的方法

  •         public StringBuilder append(任意类型)   添加数据,并返回对象本身
    • public StringBuilder reverse()         反转容器中的内容
    • pubilc  int length()        返回长度(字符出现的个数)
    • public String toString()    通过toString就可以实现把StringBuilder转换成String

注意:

因为StringBuilder是java已经写好的类,java在底层对他做了一些特殊处理,打印对象不是地址值而是属性值。

     StringBuilder sb = new StringBuilder("ABC");
        sb.append("123");
        sb.reverse();
        System.out.println(sb);
        String str = sb.toString();
        System.out.println(str);

链式编程:当我们在调用一个方法的时候,不需要用变量接收他的结果们可以继续调用其他方法。

Scanner sc=new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String str=sc.next();

        //反转键盘录入的字符串
        String result=new StringBuilder().append(str).reverse().toString();
        if(str.equals(result)){
            System.out.println("是反转字符串");
        }else{
            System.out.println("不是反转字符串");
        }

StringJoiner概述

StringJoiner跟StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的。

        作用:提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用。

JDK8出现的一个可变的操作字符串的容器,可以高效,方便的拼接字符串

构造方法:

  • Public StringJoiner(间隔符号)    创建一个StringJoiner对象,指定拼接时的间隔符号
  • Public StringJoiner(间隔符号,开始符号,结束符号)   创建一个StringJoiner对象,指定拼接时的间隔符号、开始符号、结束符号。
  • public  StringJoiner add(添加的内容)  添加数据,并返回对象本身
  • Public int  length()返回长度(字符出现的个数)
  • public String toString() 返回一个字符串(该字符串就是拼接之后的结果)
StringJoiner sj=new StringJoiner(",","[","]");
sj.add("aaa").add("bbb").add("ccc");
System.out.println(sj);

原理扩展

字符串原理

扩展底层原理1:字符串存储的内存原理

  • 直接赋值会复用字符串常量池中的
  • new出来不会复用,而是开辟一个新的空间

扩展底层原理2:==号比较的到底是什么

  • 基本数据类型比较数据值
  • 引用数据类型比较地址值

扩展底层原理3:字符串拼接的底层原理

如果没有变量参与,都是字符串直接相加,编译之后就是拼接之后的结果

如果有变量参与,会创建新的字符串,浪费内存

拼接时右边无变量:

 拼接时右边有变量:

 

扩展底层原理4:StringBuilder提高效率原理图

所有要拼接的内容都会往StringBuilder中放,不会创建很多无用的空间,节约内存

 常见面试题

 

 扩展底层原理5:StringBuilder源码分析

  • 默认创建一个长度为16的字节数组
  • 添加的内容长度小于16,直接存
  • 添加的内容大于16会扩容(原来的容量*2+2)
  • 如果扩容之后还不够,以实际长度为准

练习:

1.罗马数字转换

package test02;

import java.util.Scanner;

public class hellowworldTest {

    public static void main(String[] args) {
        String str;
        while (true) {
            //1.录入字符串
            System.out.println("请输入一个字符串:");
            Scanner sc=new Scanner(System.in);
            str=sc.next();

            //2.判断字符串是否符合要求
            boolean request=Judge(str);
            if(request){
                break;
            }else{
                System.out.println("当前的字符串不符合要求");
                continue;
            }

        }
//        //3.用罗马数字进行拼接
//        str=Replace(str);
//        System.out.println(str);
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<str.length();i++){
            char c=str.charAt(i);
            String s=changeLuoMa(c);
            sb.append(s);
        }
        System.out.println(sb);
    }
    public static String changeLuoMa(char number){
        String str=switch(number){
            case '0'->"";
            case '1'->"Ⅰ";
            case '2'->"Ⅱ";
            case '3'->"Ⅲ";
            case '4'->"Ⅳ";
            case '5'->"Ⅴ";
            case '6'->"Ⅵ";
            case '7'->"Ⅶ";
            case '8'->"Ⅷ";
            case '9'->"Ⅸ";
            default -> str="" ;
        };
        return str;
    }

//    public static String Replace(String str){
//        char [] luoma={' ','Ⅰ','Ⅱ','Ⅲ','Ⅳ','Ⅴ','Ⅵ','Ⅶ','Ⅷ','Ⅸ'};
//        for(int i=0;i<str.length();i++){
//            char c=str.charAt(i);
//            int index=(((int)c)-'0');
//            str=str.replace(c,luoma[index]);
//
//        }
//        return str;
//
//    }

    public static boolean Judge(String str){
        if(str.length()>9){
            return false;
        }
        for(int i=0;i<str.length();i++){
            char c=str.charAt(i);
            if(c<'0'||c>'9'){
                return false;
            }
        }
        return true;
    }


}

str.toCharArray() 将字符串转换为字符数组。

package test02;

public class hellowworldTest {

    public static void main(String[] args) {

        //套路:
        //修改字符串的内容
        //1.用substring进行截取,把左边的字符截取出来拼接到右侧去
        //2.可以把字符串先变成一个字符数组,然后调整字符数组里面数据,最后再把字符数组变成字符串
        String strA = "abcde";
        String strB = "cefab";

        //1.旋转字符串,并比较
        int i = 0;//记录比较次数
        while (!strA.equals(strB) && i < strA.length()) {
            strA = rotate(strA);
            i++;
            // System.out.println(strA+" "+i);

        }
        if (strA.equals(strB)) {
            System.out.println("TRUE");
        } else {
            System.out.println("FALSE");
        }


    }

    //作用:旋转字符串,将左边字符串旋转到右边去
    //形参:旋转前的字符串
    //返回值:旋转后的字符串
    public static String rotate(String str) {
//        //1.用substring截取
//        char first = str.charAt(0);
//        String end = str.substring(1);
//        return end + first;
        //2.可以把字符串先变成一个字符数组,然后调整字符数组里面数据,最后再把字符数组变成字符串
        //"ABC" ['A','B','C']
        char[] arr = str.toCharArray();
        //拿到0索引上的字符
        char first = arr[0];
        //把剩余的字符依次往前挪一个位置
        for (int i = 1; i < arr.length; i++) {
            arr[i - 1] = arr[i];
        }
        arr[arr.length - 1] = first;

//利用字符数组创建一个字符串对象
        String result = new String(arr);
        return result;
    }


}

十一、集合

自动扩容

集合存储数据类型的特点:只能存引用数据类型,基本数据类型存储时要变成包装类

ArrayList

在java.util包下,需要导包

泛型:限定集合中存储数据的类型
        ArrayList<String> list=new ArrayList<>();
        //此时我们创建的是ArrayList的对象,而ArrayList是java已经写好的一个类
        //这个类在底层做了一些处理
//        打印对象不是地址值,而是集合中存储的数据内容
//                在展示的时候会拿[]把所有的数据进行包裹
        System.out.println(list);//[]

 ArrayList成员方法

       //1.创建一个对象
        ArrayList<String> list = new ArrayList<>();
        //2.添加元素--返回值是true
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");
        list.add("bbb");
//        //3.删除元素
//        boolean result1 = list.remove("aaa");
//        System.out.println(result1);//true
//
//        boolean result2 = list.remove("eee");//删除内容不存在,删除失败
//        System.out.println(result2);//false
//        //3.根据索引删除
//
//        String str = list.remove(2);//返回被删除的字符串
//        System.out.println(str);//ddd
//        //4.修改
//        String str = list.set(1, "eee");//返回被覆盖的元素
//        System.out.println(str);//bbb

        //5.查询
//        String str=list.get(1);
//        System.out.println(str);//bbb
        //遍历--list.fori
        for (int i = 0; i < list.size(); i++) {
           String str= list.get(i);
            System.out.print(str+" ");//aaa bbb ccc ddd bbb
        }

        System.out.println(list);

集合练习:

集合存入String和int类型

//        ArrayList<String> list=new ArrayList<>();
//
//        list.add("aaa");
//        list.add("aaa");
//        list.add("aaa");
//        list.add("aaa");
//        list.add("aaa");
//
//        System.out.print("[");
//        for (int i = 0; i < list.size(); i++) {
//            if(i== list.size()-1){
//                System.out.print(list.get(i));
//            }else{
//                System.out.print(list.get(i)+",");
//            }
//        }
//        System.out.print("]");
        ArrayList<Integer> list=new ArrayList<>();
        list.add(1);
        list.add(1);
        list.add(1);
        list.add(1);
        list.add(1);
        System.out.println(list);

 集合存入自定义类

   Scanner sc=new Scanner(System.in);

        ArrayList<girlFriend> list=new ArrayList<>();
        for(int i=0;i<3;i++){
            girlFriend gf=new girlFriend();
            System.out.println("请输入姓名:");
            String name=sc.next();
            gf.setName(name);
            System.out.println("请输入年龄:");
            int age=sc.nextInt();
            gf.setAge(age);
            list.add(gf);
        }
        for (int i = 0; i < list.size(); i++) {

            System.out.println(list.get(i).getName()+" "+list.get(i).getAge());
        }
package test01;

import java.util.ArrayList;

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

//定义集合
        ArrayList<girlFriend> list=new ArrayList<>();
        //存入三个对象
        girlFriend gf1=new girlFriend("小米",1000);
        girlFriend gf2=new girlFriend("苹果",8000);
        girlFriend gf3=new girlFriend("锤子",2999);
        list.add(gf1);
        list.add(gf2);
        list.add(gf3);

        ArrayList<girlFriend> gfInFoList=judgePrice(list);
        for (int i = 0; i < gfInFoList.size(); i++) {
            girlFriend gf=gfInFoList.get(i);
            System.out.println(gf.getBrand()+" "+gf.getPrice());
        }


    }
    //返回价格低于3000的手机信息
    //技巧:
    //如果我们要返回多个数据,可以把这些数据放在一个容器里,再把容器返回
    //集合  数组
    public static ArrayList<girlFriend> judgePrice(ArrayList<girlFriend> list){
        ArrayList<girlFriend> resultList=new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            girlFriend gf=list.get(i);
            int price=gf.getPrice();
            if(price<3000){
                resultList.add(gf);
            }
        }
        return resultList;

    }
}

 十二、面向对象进阶

static 

static表示静态,是java中的一个修饰符,可以修饰成员方法,成员变量

被static修饰的成员变量,叫做静态变量

特点:

  • 被该类所有对象共享
  • 不属于对象,属于类
  • 随着类的加载而加载,优先于对象存在

调用方法:

  • 类名调用(推荐)
  • 对象名调用

被static修饰的成员方法,叫做静态方法。

  • 多用在测试类和工具类中
  • javabean类中很少会使用

 工具类:帮助我们做一些事情的,但是不描述任何事物的类

  • 类名见名知意
  • 私有化构造方法
  • 方法定义为静态

javabean类:用来描述一类事物的类

测试类:用来检查其他类是否书写正确,带有main方法的类,是程序的入口

package staticdemo1;

public class ArrayUtil {

    //私有化构造方法
    //目的:为了不让外界创建他的对象
    private ArrayUtil(){}

    //需要定义为静态的,方便调用
    public static String printArr(int []arr){
        StringBuilder sb=new StringBuilder();
        sb.append("[");
        for (int i = 0; i < arr.length; i++) {
            if(i==arr.length-1){
                sb.append(arr[i]);
            }else{
                sb.append(arr[i]).append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }

    public static double getAverage(double[]arr){
        double sum=0;
        for (int i = 0; i < arr.length; i++) {
            sum=sum+arr[i];
        }
        return sum/arr.length;
    }
}

---------------------------------------------------------------------
package staticdemo1;

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

        int []arr1={1,2,3,4,5};
        String s=ArrayUtil.printArr(arr1);
        System.out.println(s);

        double []arr2={12.5,13.5,45.2,12.5,12.3};
        double end=ArrayUtil.getAverage(arr2);
        System.out.println(end);
    }
}


static的注意事项

  • 静态方法只能访问静态变量和静态方法
  • 非静态方法可以访问静态变量或者静态方法,也可以访问非静态的成员变量和非静态的成员方法、静态方法中没有this关键字

 

 

 继承

java中提供一个关键字extend,用这个关键字,我们可以让一个类和另一个类建立起起继承关系。


public class 子类 extends 父类{}
eg:
public class Student extends Person{}

Student称为子类(派生类),Person称为父类(基类或超类)。

使用继承的好处:

  • 可以把多个子类中重复的代码抽取到中,提高代码的复用性。
  • 子类可以在父类的基础上,增加其他的功能,使子类更强大。

当类与类之间,存在相同(共性)的内容,并满足子类是父类中的一种,就可以考虑继承,来优化代码。

继承的特点:

  • java只支持单继承,不支持多继承,但支持多层继承。
    • 单继承:一个子类只能有一个父类。
  • 不支持多继承:子类不能同时继承多个父类。
    • 多层继承:子类A继承父类B,父类B可以继承父类C。
  • 每一个类都直接或者间接的继承与Object。

 子类只能访问父类中非私有的成员。

子类能继承父类哪些内容?

构造方法:

继承中成员变量和成员方法的访问特点:

成员变量的访问特点

就近原则:谁离我近我就用谁

先局部位置--再本类的成员位置---后父类成员位置,一级一级往上找

成员方法的访问特点:

直接调用满足就近原则:谁离我近,我就用谁

super调用,直接访问父类 

方法的重写

当父类的方法不能满足子类现在的需求时,需要进行方法重写。

书写格式:在继承体系中,子类出现了和父类中一模一样的方法声明,我们就成称子类这个方法是重写的方法。

@Override重写注解

1.@Override是放在重写后的方法上,校验子类重写时语法是否正确。

2.加上注解后如果有红色波浪线,表示语法错误。

3.建议重写方法都加@Override注解,代码安全,优雅!

 方法重写注意事项和要求:

1.重写方法的名称、形参列表必须与父类中的一致。

2.子类重写父类方法时,访问权限子类必须大于等于父类(暂时了解:空着不写<protected<public)。

3.子类重写父类方法时,返回值类型子类必须小于等于父类。

4.建议:重写的方法尽量和父类保持一致

5.只有被添加到虚方法表中的方法才能被重写

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

  • 父类的构造方法不会被子类继承
  • 子类中所有的构造方法默认先访问父类中的无参构造,再执行自己
    • 为什么?
      • 子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。
      • 子类初始化之前,一定要调用父类构造方法先完成父类数据空间的初始化。
    • 怎么调用父类构造方法的
      • 子类构造方法的第一行语句默认都是:super(),不写也存在,且必须在第一行
      • 如果想调用父类有参构造,必须手写super进行调用。
package staticdemo1;

public class TestDemo1 {
    public static void main(String[] args){
        Student s1=new Student();
        //输出:父类的无参构造
        //     子类的无参构造
        Student s2=new Student("张三",16);
        System.out.println(s2.name+" "+s2.age);//输出:张三 16


    }

}
class Person{
   String name;
   int age;

public Person() {
    System.out.println("父类的无参构造");
}

    public Person(String name,int age) {
        this.name = name;
        this.age=age;
    }
}
class Student extends Person{
    public Student() {
        //子类中隐藏的super去访问父类的无参构造
        System.out.println("子类的无参构造");
    }

    public Student(String name, int age) {
        super(name, age);//调用父类的有参构造
    }
}

this、super使用总结:

  • this:理解为一个变量,表示当前方法调用者的地址值。
  • super:代表父类存储空间。

package staticdemo1;

public class TestDemo1 {
    public static void main(String[] args){
        Student s1=new Student();
        System.out.println(s1.name+" "+s1.age+" "+s1.school);//null 0 传智大学
        Student s2=new Student("张三",16,"黑马");
        System.out.println(s2.name+" "+s2.age+" "+s2.school);//张三 16 黑马


    }

}
class Person{
   String name;
   int age;



public Person() {
    System.out.println("父类的无参构造");
}

    public Person(String name,int age) {
        this.name = name;
        this.age=age;
    }
}
class Student extends Person{
    //需求:
    //默认为传智大学
    String school;
    public Student() {
      //表示调用本类的其他构造方法;
        //细节:虚拟机就不会再添加super()方法。因为其他构造中有
        this(null,0,"传智大学");

    }

    public Student(String name, int age,String school) {
      super(name,age);
      this.school=school;
    }
}

 多态

什么是多态?

        同类型的对象,表现出不同形态,对象的多种形态

多态的表现形式

父类类型 对象名称=子类对象;

多态的前提

  • 有继承/实现关系
  • 有父类引用指向子类对象
  • 有方法重写

多态调用成员的特点

调用成员变量编译看左边,运行也看左边

编译看左边:javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功,如果没有编译失败。

运行也看左边:java运行代码的时候,实际获取的就是左边父类中成员变量的值。

调用成员方法编译看左边,运行看右边

编译看左边:javac编译代码的时候。会看左边的父类中有没有这个方法,如果有,编译成功,如果没有编译失败。

运行看右边:java运行代码的时候,实际上运行的是子类中的方法。

成员变量:在子类的对象中,会把父类的成员变量也继承下的。

成员方法:如果子类对方法进行了重写,那么在虚方法表中是会把父类的方法进行覆盖的

多态的优缺点

  • 优势:
    • 在多态形式下。右边对象可以实现解耦合,便于扩展和维护。
    • 定义方法的时候,使用父类类型为参数,可以接受所有子类对象,体现多态的扩展性与便利
  • 弊端:
    • 不能调用子类特有的功能
    • 原因:当调用成员方法时,编译看左边,运行看右边。那么在编译的时候会先检查左边的父类中有没有这方法,如果没有直接报错。
    • 解决方法:变回子类类型就可以了,注意转换时不能瞎转没如果转成其他类型,会报错。
package staticdemo1;

public class test {
    public static void main(String[] args) {
        Animal a=new dog();
//类型强转
//方法·1
//        if(a instanceof dog){
//            dog d=(dog)a;
//            d.LookHome();
//        }else if(a instanceof cat){
//            cat c=(cat)a;
//            c.CatchMouse();
//        }else{
//            System.out.println("没有这个类型,无法转换");
//        }
//方法2
        if(a instanceof dog d){
            d.LookHome();
        }else if(a instanceof cat c){
            c.CatchMouse();
        }else{
            System.out.println("没有这个类型,无法转换");
        }

    }
}

引用数据类型的类型转换,有几种方式?

自动类型转换、强制类型转换

强制类型转换能解决什么问题?

  • 可以转换成真正的子类类型,从而调用子类独有的功能
  • 转换类型与真实对象类型不一致会报错
  • 转换的时候用 instanceof 关键字进行判断
package staticdemo1;

public class test {
    public static void main(String[] args) {
        Animal a=new cat(3,"灰");
        person p=new person("老王",30);
        p.keepPet(a,"小鱼干");


        Animal a2=new dog(2,"黑");
        person p2=new person("老李",25);
        p2.keepPet(a2,"骨头");

    }
}

-----------------------------------------------------
package staticdemo1;

public class Animal {

    //属性
    private int age;
    private String color;

    public Animal() {
    }

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

    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(String something){
        if(this instanceof dog d){
            d.eat(something);
        }else if(this instanceof  cat c){
            c.eat(something);
        }


    }

}
---------------------------------------------
package staticdemo1;

public class cat extends Animal{
    public cat() {
    }

    public cat(int age, String color) {
        super(age, color);
    }

    public void catchMouse(){
        System.out.println("猫逮老鼠");
    }

    @Override
    public void eat(String something) {
        System.out.println(getAge()+"岁的"+getColor()+"颜色的猫眯着眼睛侧着头吃"+something);
    }
}
----------------------------------------------
package staticdemo1;

public class dog extends Animal{
    public dog() {
    }

    public dog(int age, String color) {
        super(age, color);
    }

    public void lookHome(){
        System.out.println("狗看家");
    }

    @Override
    public void eat(String something) {
        System.out.println(getAge()+"岁的"+getColor()+"颜色的狗两只前腿死死的抱住"+something+"猛吃");
    }
}
----------------------------------------------------------------
package staticdemo1;
//饲养员
public class person {
    private String name;
    private int age;

    public person() {
    }

    public person(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 keepPet(Animal a,String something){
        System.out.print("年龄为"+getAge()+"岁的"+getName()+"养了一只"+a.getColor()+"颜色的"+a.getAge()+"岁的");
      if(a instanceof dog d){
          System.out.println("狗");
          d.eat(something);

      }else if(a instanceof cat c){
          System.out.println("猫");
          c.eat(something);
      }

    }

}

什么是包?

包就是文件夹。用来管理各种不同功能的java类,方便后期维护代码维护。

包名的规则:公司域名反写+包的作用,需要全部英文小写,见名知意。

全类名/全限定名

包名+类名

eg:

使用其他类的规则

使用其他类时,需要使用全类名

  •  使用同一个包中的类时,不需要导包
  • 使用java.lang包中的类时,不需要导包
  • 其他情况都需要导包
  • 如果同时使用两个包中的同名类,需要用全类名

final--最终的

可以修饰方法、类、变量。

方法:表明该方法时最终方法,不能被重写

类:表明该类是最终类,不能被继承

变量:叫做常量,只能被赋值一次

常量

实际开发中,常量一般作为系统的配置信息,方便维护,提高可读性

常量的命名规范:

  • 单个单词:全部大写
  • 多个单词:全部大写,单词之间用下划线隔开

细节:

final修饰的变量是基本类型:那么变量存储的数据值不能发生改变

final修饰的变量是引用类型:那么变量存储的是地址值不能发生改变,对象内部的可以改变。

private static final PI="3.14159";

权限修饰符

  • 权限修饰符:是用来控制一个成员能够被访问的范围的。
  • 可以修饰成员变量,方法,构造方法,内部类。

权限修饰符的分类:

有四种作用范围:由小到大:

private<空着不写(默认)<protected<public

 权限修饰符使用规则

实际开发中,一般只用private和public

使用时一般:

  • 成员变量私有
  • 方法公开

特例:如果方法中的代码时抽取其他方法中共性代码,这个方法一般也私有。

代码块

局部代码块

写在方法里面的代码块

构造代码块

1.写在成员位置的代码块

2.作用:可以把多个构造方法中的重复代码抽取出来

3.执行时机:我们在创建本类对象的时候会先执行构造代码块在执行构造方法

渐渐淘汰了,不够灵活

如果构造方法中有重复代码,可以用以下两种方法:

静态代码块

格式:static{ }

特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次

使用场景:在类加载的时候,做一些数据初始化且这些数据初始化只想使用一次的时候使用。

抽象类与抽象方法

  • 抽象方法:

        将共性的行为(方法)抽取到父类之后。由于每一个子类执行的内容是不一样,所以,再父类中不能确定具体的方法体。该方法就可以定义为抽象方法。

  • 抽象类:如果一个类中存在抽象方法,那么该类就必须声明名为抽象类

抽象方法的定义格式:

        public abstract 返回值类型 方法名(参数列表);

抽象类的定义格式:

        public abstract class 类名 {}

抽象类和抽象方法的注意事项:

  • 抽象类不能实例化--即不能创建对象
  • 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
  • 可以有构造方法
  • 抽象类的子类
    • 要么重写抽象类中的所有抽象方法
    • 要么是抽象类
package test05;

public abstract class Animal {
    private String name;
    private int age;

    public Animal() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }
    public void drink(){
        System.out.println("动物在喝水");
    }

    public abstract void eat();
}


------------------------------------------------------------
package test05;

public class Sheep extends Animal{

    public Sheep() {
    }

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

    @Override
    public void eat() {
        System.out.println("山羊吃草");
    }
}

抽象方法和抽象类的意义

强制子类必须按照这种格式书写

接口

接口就是一种规则,是对行为的一种抽象

接口和抽象类:抽象类多用在父类中

 格式:

public class 子类g extends 父类 implements 接口1,接口2....{
....
}

 例子:

package test05;

public interface swim {
    public abstract void swim();
}
------------------------------------------
package test05;

public class Dog extends Animal implements swim{


    public Dog() {
    }

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

    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    @Override
    public void swim() {
        System.out.println("狗在游泳");
    }
}

接口中成员的特点

  • 成员变量

                只能是常量

                默认修饰符:public static final ...

  • 构造方法

                没有

  • 成员方法 

                只能是抽象方法

                默认修饰符:public abstract

  • JDK7以前:接口中只能定义抽象方法

接口和类之间的关系

  • 类和类之间的关系
    • 继承关系,只能单继承,不能多继承,但是可以多层继承
    • 如果实现类实现了最下面的子接口,那么就需要重写所有的抽象方法
  • 类和接口的关系
    • 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口-要重写里面所有的抽象方法
  • 接口和接口的关系
    • 继承关系,可以单继承,也可以多继承

例子:

package test05;

public class InterImp1 implements Inter3{


    @Override
    public void method1() {
        
    }

    @Override
    public void method2() {

    }

    @Override
    public void method3() {

    }
}
----------------------------------------------------
package test05;

public interface Inter3 extends Inter1, Inter2{
    public abstract void method3();
}
-------------------------------------------------------
package test05;

public interface Inter2 {
    public abstract void method2();

}
-----------------------------------------------------
package test05;

public interface Inter1 {
    public abstract void method1();
}

JDK8开始接口中的新增方法

JDK7以前:接口中只能定义抽象方法。

JDK8的新特性:接口中可以定义有方法体的方法(默认、静态)。

JDK9的新特性:接口中可以定义私有方法。

  • 允许在接口中定义默认方法,需要使用关键字default修饰
    • 作用:解决接口升级问题
    • 接口中默认方法的定义格式:
      • 格式:public default 返回值类型 方法名(参数列表){ }
      • 范例:public default void show() {}
    • 接口中默认方法的注意事项:
      • 默认方法不是抽象方法,所以不强制重写。但是如果被重写,重写的时候必须去掉default关键字。
      • public可以省略,default不能省略。
      • 如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写
  • 允许在接口中定义静态方法,需要用static修饰
    • 接口中静态方法的定义格式:
      • 格式:public static 返回值类型 方法名(参数列表) { }
      • 范例:public static void show() {}
    • 接口中静态方法的注意事项:
      • 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
      • public 可以省略,static不能省略
    • 注意:
      • package test05;
        
        public interface Inter1 {
           
            public static void show1(){
                System.out.println("Inter中的静态方法");
            }
        }
        ---------------------------------------------
        package test05;
        
        public class InterImp1 implements Inter1{
        
        
            //不叫重写,只是这两个接口中的静态方法同名而已
            public static void show1(){
                System.out.println("InterImp1中的静态方法");
            }
        }
        ---------------------------------------------
        package test05;
        
        public class Test {
        
            public static void main(String[] args) {
              InterImp1 i1 =new InterImp1();
              i1.show();
        
              //调用接口中的静态方法
                InterImp1.show1();//Inter中的静态方法
            //调用实现类中的静态方法
                InterImp1.show1();//InterImp1中的静态方法
        //子类把父类继承下来的虚方法表里面的方法进行覆盖了,这才叫做重写
            }
        }
        

JDK9新增的方法--解决重复代码

  • 接口中私有方法(此方法只为接口提供服务,不需要外类访问)的定义格式
    • 普通的私有方法,给默认方法服务的
      • 格式一: private 返回值类型 方法名(参数列表){ }
      • 范例一:private void show() {}
    • 静态的的私有方法,给静态方法服务的
      • 格式二:private static 返回值类型 方法名(参数列表){}
      • 范例二:private static void method() { }
package test06;

public interface InterA {
    public default void show1(){
        System.out.println("show1方法开始执行了");
        show3();
    }
    public default void show2(){
        System.out.println("show2方法开始执行了");
        show3();
    }
    
    //普通的私有方法
    private void show3(){
        System.out.println("这里有100行show1,show2的重复代码");

    }
    
    
    
    public static void show4(){
        System.out.println("show1方法开始执行了");
        show6();
    }
    public static  void show5(){
        System.out.println("show2方法开始执行了");
        show6();
    }

    //静态的私有方法
    private static  void show6(){
        System.out.println("这里有100行show4,show5的重复代码");

    }
    
}

 接口的应用

  1. 接口代表规则,是行为的抽象。想要让哪个类拥有一个行为,就让这各类实现对应的接口就可以了。
  2. 当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称之为接口多态

 适配器设计模式

简单理解:设计模式就是各种套路

适配器设计模式:解决接口与接口实现类之间的矛盾问题

当一个接口中抽象方法过多,但是我只要使用其中一部分的时候,就可以用适配器设计模式。

2.书写步骤:

        编写中间类xxxAdapter,实现对应的接口

        对接口中的抽象方法进行空实现

        让真正的实现类继承中间类,并重写需要用的方法

        为了避免其他类创建适配器类的对象,中间的适配器类用abstract进行修饰。

内部类 

类的五大成员:

属性、方法、构造方法、代码块、内部类

内部类:在一个类的内部再定义一个类,这个类称为内部类

  内部类的访问特点:

1.内部类可以直接访问外部类的成员,包括私有

2.外部类要访问内部类的成员,必须创建对象。

什么时候用到内部类?

B类表示的事物是A类的一部分,且B单独存在没有意义。

内部类的分类

成员内部类、静态内部类、局部内部类(前三个了解)和匿名内部类(掌握)。

成员内部类
  • 写在成员位置的,属于外部类的成员。
  • 成员内部类可以被一些修饰符所修饰,比如:private,默认,protected,public,static等
  • 在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量。
获取成员内部类对象

方法一:在外部类中编写方法,对外提供内部类的对象。----当成员内部类被private修饰时

方法二:直接创建格式:--------当成员内部类被非私有修饰时

外部类名.内部类名 对象名=外部类对象.内部类对象

package test07;

public class Out {
    String name;

    private class Inner{

    }
    public Inner getInstance(){
        return new Inner();
    }


}
-----------------------------------------------
package test07;

public class Test {
    public static void main(String[] args) {
        //是否能用与内部类的权限修饰符有关
       // Out.Inner oi=new Out().new Inner();


        Out o=new Out();
        System.out.println(o.getInstance());
    }
}

外部类成员变量与内部类成员变量重名时,在内部类如何访问?

        外部类名.this.变量名

 

静态内部类

 静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象

package test07;

public class Car {
   int a=10;
   static int b=20;

   //静态内部类
   static class Inner {
      public void show1(){
         //要访问a,需要创建对象
         Car c=new Car();
         System.out.println(c.a);
         //b可以直接访问
         System.out.println(b);
         //System.out.println("非静态方法被调用了");
      }

      public static void show2(){
         //要访问a,需要创建对象
         Car c=new Car();
         System.out.println(c.a);
         //b可以直接访问
         System.out.println(b);
         //System.out.println("静态方法被调用了");
      }

   }
}

 创建静态内部类对象的格式:外部类.内部类 对象名=new 外部类名.内部类名();

调用非静态方法的格式:先创建对象,用对象调用

调用静态方法的格式:外部类名.内部类名.方法名();





package test07;

public class Car {
   int a=10;
   static int b=20;

   //静态内部类
   static class Inner {
      public void show1(){

         System.out.println("非静态方法被调用了");
      }

      public static void show2(){

        System.out.println("静态方法被调用了");
      }

   }
}
----------------------------

package test07;

public class Test {
    public static void main(String[] args) {
//创建静态内部类的对象
        //只要是静态的东西,都可以用类名之间获取
        Car.Inner ci=new Car.Inner();
        ci.show1();

        //静态方法
        //用ci.show2()也可以,但是不推荐
        Car.Inner.show2();


    }
}
局部内部类
  • 将内部类定义在方法里面就叫局部内部类,类似于方法里面的局部变量
  • 外界是无法直接使用局部内部类,需要在方法内部创建对象并使用
  • 该类可以直接访问外部类的成员,也可以访问方法内的局部变量
package test07;

public class Car {
   int a=10;
   public void show(){

      int b=20;

      //局部内部类
      class Inner{
         String name;
         int age;

         public void method1(){
            System.out.println(a);
            System.out.println(b);
            System.out.println("局部内部类中的method1方法");
         }

         public static void method2(){
            System.out.println("局部内部类中的method2静态方法");
         }
      }
      //创建局部内部类的对象
      Inner i=new Inner();
      System.out.println(i.age);
      System.out.println(i.name);
      i.method1();
      Inner.method2();

   }


}

--------------------------------------------------------------

package test07;

public class Test {
    public static void main(String[] args) {
        //创建对象,调用show方法
        Car c=new Car();
        c.show();

    }
}
----------------
//输出
0
null
10
20
局部内部类中的method1方法
局部内部类中的method2静态方法

匿名内部类(重要)

匿名内部类本质上就是隐藏了名字的内部类

什么是匿名内部类?

隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置。

格式的细节:

包含了继承或实现关系、方法重写、创建对象。

整体就是一个类的子类对象或者接口的实现对象

使用场景:

当方法的参数是接口或者类时,

以接口为例,可以传递这个接口的实现类对象

如果实现类只要使用一次,就可以用匿名内部类简化代码。

格式:

new 类名或者接口名(){
    
    重写方法;

};

eg:

new Inter(){

    public void show(){
    
    }

}

package test07;

public abstract class Animal {
    public abstract void eat();
}
--------------------------------
package test07;

public class Dog extends Animal{

    @Override
    public void eat() {
        System.out.println("重写eat抽象方法");
    }
}

--------------------------------

package test07;

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

        //在测试类中调用下面的method方法?
        //以前:
        //要自己写一个子类继承Animal类
        //再创建子类的对象,传递给method方法
//        Dog d=new Dog();
//        method(d);

        //如果Dog类我只用一次,那么还需要单独定义一个类太麻烦了。
        method(
                new Animal() {
                    @Override
                    public void eat() {
                        System.out.println("狗吃骨头");

                    }
                }
        );


    }
    public static void method(Animal a){//Animal a=子类对象 多态

        a.eat();//编译看左边,运行看右边
    }
}
-------------------------------------------------------------
枚举
  • 枚举是一种特殊类
  •  枚举类的格式     
修饰符 enum 枚举类名{
    名称1,名称2;
    其他成员;


}

注意:

  • 枚举类中的第一行,只能写一些合法的标识符(名称),多个名称用逗号隔开。
  • 这些名称,本质是常量,每个常量都会记住枚举类的一个对象。

  •  枚举类的第一行只能罗列一些名称,这些名称都是常量,并且每个常量记住的都是枚举类的一个对象。
  • 枚举类都是最终类,不可以被继承。
  • 枚举类中,从第二行开始,可以定义类的其他各种成员
  • 编译器为枚举类新增了几个方法,并且枚举类都是继承:java.lang.Enum类的,从enum类也会继承到一些方法。
  • 枚举类的构造器都是私有的(写不写都是私有的),因此,枚举类对外不能创建对象。

阶段项目

事件

事件是可以被组件识别的操作。

当你对组件干了某件事情之后,就会执行对应的代码。

事件源:按钮 图片 窗体.....

事件:某些操作

        如:鼠标单击,鼠标划入...

绑定监听:当事件源上发生了某个事件,则执行某段代码

KeyListener      MouseListener       ActionListener

键盘监听                鼠标监听                动作监听(鼠标左键点击和空格)

特殊类

1.获取随机数

1.导包  import  java.util.Random;

导包的动作必须出现在类定义的上边。

2.创建对象---表示要是开始用Random这个类了

Random r=new Random;

上面这个格式里面,只有r是变量名,可以变,其他的都不允许变。

3.生成随机数---真正开始干活了

Int number=r.nextint(随机数的范围);

上面这个格式里面,只有number是变量名,可以变,其他的都不允许变。

判断范围:

在小括号内,书写的是生成随机数的范围,范围是从0开始的,到数-1结束

口诀:包头不包尾,包左不包右

IDEA快捷操作

Ctrl+alt+l  格式化代码,让代码变齐

Ctrl+/        单行注释或解除注释

Ctrl+shift+/  多行注释或解除注释

按住鼠标滚轮 或者 按住alt 不松,再拖动,可以同时修改选中的代码

alt+insert  可选constructor设置构造方法和选Getter and Setter 来设置setX,getX

或者安装ptg插件后,右键导入javabean.

Ctrl +alt+v 自动生成左边

对于数组用for循环遍历时,可以用

 对一串代码加循环,选中要加循环的代码后按ctrl+alt+t

选住后按shift+f6  批量修改

选中方法,ctrl+b跟进

ctrl+z 撤销操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: JMU Java 03面向对象基础-01-构造函数和toString方法。 构造函数是一种特殊的方法,在创建对象时自动调用,用于初始化对象的状态。 toString方法是Java中的一个方法,它可以返回对象的字符串表示形式,方便调试和打印输出。 ### 回答2: 构造函数和toString()是Java语言中的两个重要概念,它们是面向对象编程中的基础知识。本文将从以下几个方面来回答该问题: 一、构造函数 构造函数是一种特殊的方法,用于创建对象并初始化该对象的属性。一个类可以有多个构造函数,每个构造函数可以接受不同的参数,从而实现不同的对象初始化方式。在Java中,构造函数的名称与类名称相同,它没有任何返回值,包括void。 有两种类型的构造函数,即默认构造函数和带参数构造函数。默认构造函数没有任何参数,Java会自动为每个类提供一个默认的构造函数,它会执行以下操作: 1、初始化类的属性。 2、如果类继承自其他类,则会自动调用父类的构造函数。 如果一个类定义了带参数构造函数,则默认构造函数就不再自动提供。带参数构造函数可以自定义对象的初始化方式,提供不同的参数初始化对象的属性。带参数构造函数的声明格式为: public 类名(参数列表){ } 二、ToString()方法 toString()是对象类中的一个方法,它返回一个表示该对象的字符串。通常情况下,该字符串包括了对象的类名和属性值,以便于在需要时打印对象信息。 在Java中,如果没有显式地定义toString()方法,则默认使用Object类中的默认方法,该方法返回一个格式为“类名@哈希值”的字符串。但通常情况下,我们需要重新定义toString()方法,以便获取对象的更详细的信息,比如对象的属性。 对象类中重写toString()方法的格式如下: public String toString(){ } 值得注意的是,toString()方法可以被覆盖或者重新定义,但它必须返回一个字符串对象,否则将会出现编译错误。 结论: 构造函数和toString()是Java面向对象编程中的两个基本概念,这两者的作用分别是为对象初始化和展示对象信息。在实际工作中,我们需要充分理解这两个概念的含义和用途,从而更好的利用Java的面向对象编程方式。 ### 回答3: Java是一门面向对象的语言,构造函数和toString是面向对象编程中常用的两种方法之一。构造函数是用于创建对象的特殊方法,它可以在创建新对象时执行必要的初始化操作。而toString方法则是将对象转化为指定格式的字符串。在Java开发中,学习和熟练使用构造函数和toString方法对于编写高效,易于维护且易于阅读的代码非常重要。 首先,构造函数是一个类的特殊方法,它与类同名,并且不需要显式调用。当我们创建一个新对象时,构造函数被自动调用。在构造函数中,通常会执行一些初始化操作,如为对象的属性赋初始值。构造函数可以根据参数列表的不同,有多个重载版本。这样,我们可以根据需要以不同的方式创建对象,并且可以灵活地控制对象的初始化过程。 其次,toString方法是将对象转化为字符串的常用方法之一。它通常在输出对象时调用,将对象的属性转化为字符串并输出。在自定义类中,我们可以自己实现toString方法来控制对象转换成字符串的格式。对于调试和日志记录等任务,toString方法非常有用。它可以方便地将对象的状态输出到控制台或日志文件中,便于我们了解程序的运行状态和调试程序。 在使用构造函数和toString方法时,我们需要注意一些问题。首先,构造函数应该执行必要的初始化操作,但不应该执行过多的计算或IO操作。因为构造函数执行的时间可能很长,这会导致性能问题。其次,toString方法应该返回一个稳定的字符串。这样,我们在不同的场景下输出这个对象时,可以获得相同的输出。最后,我们需要为自己的类实现好构造函数和toString方法,以方便其他人阅读、使用和理解我们的代码。 总的来说,构造函数和toString方法是Java面向对象编程中重要的基础知识。它们是我们创建和操作对象不可或缺的工具。通过熟练掌握这两个方法,我们可以写出更加健壮和易于维护的代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值