JavaSE学习笔记

JavaSE学习笔记,

学习视频-狂神说JavaSE:视频链接

JavaSE

预科

Typora的序列号免费获取方式:
写博客:
  1. 注册网站后,写博客(如:博客园、CSDN);

  2. 买服务器,搭建自己的网站,写博客;

    • 自己设计网站样式

    • 通过网站设计模板快速设计样式,如:wordpress、typecho主题

windows常用快捷键:
  • Ctrl+C :复制

  • Ctrl+V :粘贴

  • Ctrl+A :全选

  • Ctrl+X :剪切

  • Ctrl+Z :撤销

  • Ctrl+S :保存

  • Alt+F4 :关闭窗口

  • Shift+Delete :永久删除

  • Windows+R :运行

  • Windows+E :打开此电脑

  • Windows+Tab :切换应用程序

  • Ctrl+Shift+Esc :任务管理器

打开cmd的方式:
  1. 开始+Windows系统+命令提示符

  2. Windows+R→输入cmd→打开控制台

  3. Shift+鼠标右键→在此处打开PowerShell窗口

  4. 资源管理器的地址栏前面加上:cmd 路径(cmd+空格)

  5. 搜索栏输入cmd→运行

  • 管理员方式运行:选择以管理员方式运行
常用的Dos命令:
D:			#盘符切换
dir			#查看当前目录下的所有文件、文件夹
cd			#切换目录(change directory)
cd ..		#返回上级目录
cls			#清理屏幕(clear screen)
cd xx		#切换到下级目录
cd /d F:\xx	#切换到其他盘目录
exit		#退出终端
ipconfig	#查看电脑的IP
#打开应用:
	calc	#打开计算器
    mspaint	#打开画图工具
    notepad	#打开记事本
#ping命令
	ping www.baidu.com
#文件操作
	md	目录名	#创建test目录
	rd	目录名	#删除test目录
	cd>	文件名	#创建a.txt文件
	del	文件名	#删除a.txt文件

Java入门

Java帝国的诞生
  • 1972年C诞生→1982年C++诞生→1995年Java
Java特性和优势
  • 简单性

  • 面向对象

  • 可移植性

  • 高性能

  • 分布式

  • 动态性

  • 多线程

  • 安全性

  • 健壮性

Java三大版本
  • JavaSE:标准版(桌面程序,控制台开发......)

  • JavaME:嵌入式开发(手机,小家电......)

  • JavaEE:E企业级开发(web端,服务器开发......)

JDK、JRE、JVM
  • JDK:Java开发者工具(Java Development Kit)

  • JRE:Java运行时环境(Java Runtime Environment)

  • JVM:Java虚拟机(Java Virtual Machine)

JDK开发环境搭建
下载JDK
卸载JDK
  1. 删除Java的安装包

  2. 删除JAVA_HOME

  3. 删除path下关于Java的目录

  4. 查看java -version,看是否卸载成功

安装JDK8
  1. 百度搜索JDK8,找到下载地址

  2. 同意下载协议

  3. 下载电脑对应的版本

  4. 双击安装JDK

  5. 记住安装的路径

  6. 配置环境变量

    • 此电脑→右键→属性

    • 环境变量→JAVA_HOME

    • 配置path环境变量

安装JDK17
  1. 简单配置环境变量

  2. 复杂配置环境变量

    • jdk17安装教程:复杂版

      • 安装jdk17

      • 生成jre目录:

        • 在cmd窗口,切换到JDK17的安装目录
      • 执行bin\jlink.exe --module-path jmods --add-modules java.desktop --output jre指令,生成JRE目录配置环境变量

HelloWorld
  1. 新建文件夹,用来存放代码

  2. 新建Java文件

    • 文件后缀名.java

    • Hello.java

    • 【注意点】文件后缀名如果未显示,需手动打开

  3. 编写代码

    public class Hello{
    	public static void main(String[] args){
    		System.out.println("Hello,World!");
    	}
    }
    
  4. 编译java文件→生成class文件:javac Hello.java(javac java文件)

  5. 运行class文件:java Hello(java class文件)

可能会遇到的问题:
  1. 每个单词的大小写不能出现问题,Java是大小写敏感的

  2. 尽量使用英文,(cmd控制台输出的中文,一般都会出现乱码)

  3. "文件名"与"类名"必须一致,并且根据驼峰命名规则首字母应该大写

  4. 符号必须是英文,(不能使用中文,例如:";"与";"的区别→必须是英文输入法的分号";")

程序运行机制:
  • 时机不同

    • 编译型→整体翻译→如:操作系统;C/C++
  • 解释型→一句一句的翻译→如:网页、服务器脚本(速度要求没那么高);js/python/VB

Java程序运行机制
  • Java→两者结合,接近解释性语言特征

    • 编译过程:x.java文件→x.class文件

Java程序运行机制

IDEA安装和介绍:
IDEA安装

Java基础→语法

1、注释、标识符、关键字
注释:
  • 书写注释是一个非常良好的习惯 BAT(百度、阿里、腾讯)

  • 平时写代码一定要注意规范

    • 单行注释:// 单行注释

    • 多行注释:/* 多行注释 */

    • 文档注释:/** 文档注释 */

  • 有趣的代码注释

标识符:
  • Java所有的组成部分都需要名字,类名、变量名以及方法名都被称为标识符

  • 注意点:

    • 所有的标识符都应该以字母(A-Z,a-z),美元符($),或者下划线(_)开头

    • 首字母之后可以是字母(A-Z,a-z),美元符($),下划线(_)或数字的任何字符组合

    • 不能使用关键字作为变量名或方法名

    • 标识符是大小写敏感的

    • 合法标识符举例:Aa$aD_4$$3rH_6e

    • 非法标识符举例:1Aa$#aD4$-3rH_6e

      public static void main(String[] args){
      	String 王者荣耀 = "最强王者";
          System.out.println(王者荣耀);
      } 
      
    • 可以使用中文命名,但不建议这样去使用,也不建议使用拼音,很Low

关键字:
关键字 关键字 关键字 关键字 关键字
abstract assert boolean break byte
case catch char class const
continue default do double else
enum extends final finally float
for goto if implements import
instanceof int interface long native
new package private protected public
return strictfp short static super
switch synchronized this throw throws
transient try void volatile while
2、数据类型
数据类型:
  • 强类型语言

    • 要求变量的使用严格符合规定,所有变量必须先定义才能使用

    • 安全性高,速度慢(C++,Java)

  • 弱类型语言

    • 变量的使用不严格

    • 如VB,JS

  • Java的数据类型分为两大类

    • 基本类型(primitive type)

    • 引用类型(reference type)

Java数据类型

什么是字节:
  • 位(bit):是计算机内部数据储存的最小单位,11101110是一个八二进制数(结合:百十进制理解)。

  • 字节(byte):是计算机中数据处理的基本单位,习惯上用大写B来表示

  • 1B(byte,字节)=8bit(位)

  • 字符:是指计算机中使用的字母、数字、字和符号

    • 1bit表示1位

    • 1Byte表示一个字节1B=8b

    • 1024B=1KB

    • 1024KB=1M

    • 1024M=1

  • 思考:电脑的32位和64位的区别是什么呢?

  • 整数拓展:

    • 进制→→→

      • 二进制0b ,十进制,八进制0,十六进制0x
    • 尽量避免使用浮点数比较数据大小

    • BigDecimal数学工具类→→银行业务使用

  • 字符拓展:

    • 强制转换:

      char c1='a';
      char c1='中';
      char c3='\u0061';
      System.out.println((int)c1);//结果→→97
      System.out.println((int)c2);//结果→→20013
      System.out.println(c3);		//结果→→a;
      
    • 所有的字符本质还是数字

    • 编码 Unicode 2个字节 0-65535

      • 表:(97=a,65=A)

      • U0000-UFFFF→→→'\u0000'~'\uffff'

    • 转义字符

      \'	单引号
      \"	双引号
      \\	反斜线
      \r	回车符
      \n	换行符
      \f	走纸换页
      \t	制表符、横向跳格
      \b	退格
      。。。
      
    • 对象:从内存分析

      String s1=new string("tangguo");
      String s2=new string("tangguo");
      System.out.println(s1==s2);	//结果→false
      String s3="tangguo";
      String s4="tangguo";
      System.out.println(s3==s4);	//结果→true
      
    • 布尔值扩展

      boolean flag=true;
      if (flag==true){};//新手
      if (flag){};//老手
      //Less is More!	代码要精简易读
      
3、类型转换
  • Java是强类型语言,在运算时,有时需要用到类型转换

    • 低(小范围)————————————→高(大范围)

    • byte,short,charintlongfloatdouble

  • 运算中,不同类型的数据进行运算时,需要先进行类型转换

    • 强制类型转换:(类型)变量名

      • 大范围小范围(高--低)

        int i=128;
        byte b=(int)i;//内存溢出
        System.out.println(i);//结果:128
        System.out.println(b);//结果:-128
        
    • 自动类型转换

      • 小范围大范围(低--高)

        int i=128;
        double d=i;
        System.out.println(i);//结果:128
        System.out.println(d);//结果:128.0
        
    • 操作比较大的数的时候,注意溢出问题

      • JDK7新特性,数字之间可以用下划线分割

        int money=10_0000_0000;
        int years =20;
        int total=money*years;//计算的时候溢出了
        long total2=money*((long)years);//先把一个数转换为long
        System.out.println(total2);
        
  • 注意点

    • 不能对布尔值进行转换

    • 不能把对象类型转换成不相干的类型

    • 在把高容量转换为低容量时,强制转换

    • 转换的时候可能存在内存溢出(高-低,char-short-char),或精度问题(整数-浮点数-整数

4、变量、常量
变量
  • 变量:可以变化的量

  • 变量必须声明类型

  • 变量是程序中最基本的存储单位,其要素包括变量名变量类型作用域

    • type varName[=value][{,varName[=value]}];

    • 数据类型 变量名 = 值;可以使用多个逗号来声明多个同类型变量,不建议同时定义多个

    • int a = 2;

  • 注意事项:

    • 每个变量都有类型,类型可以是基本类型,也可以是引用类型

    • 变量名必须是合法的标识符

    • 变量声明是一条完整的语句,因此每一个声明都必须以分号结束

变量作用域:
  • 类变量:static修饰static double salary=2500;

  • 实例变量:从属于对象String name;//默认null,如果不自动初始化,使用默认值0/0.0/null/false

  • 局部变量:必须声明和初始化值int i=0;

    public class Penson{
        static int allPenson=0;		// 类变量
        String strPojo="TangGuo";	// 实例变量
        
        public void method(){
            int i=0;	// 局部变量
        }
    }
    
常量
  • 常量(constant):初始化(initialize)后不能再改变的值!不会变动的值

  • 特殊的变量,值被设定后,在程序运行过程中不允许被改变

    • final 常量名 值;

    • final double PI=3.14;

  • 常量名一般使用大写字符

    • static final double PI=3.14; // 修饰符static/final...,不存在先后顺序
变量的命名规范
  • 所有变量、方法、类名:见名知意

  • 类成员变量:小驼峰原则:monthSalary

  • 局部变量:小驼峰原则

  • 常量:大写字母和下划线:MAC_VALUE

  • 类名:大驼峰原则:TangGuo

  • 方法名:小驼峰原则:runTime()

5、运算符
Java语言支持如下运算符:
  • 优先级:多加()不需要刻意去记

  • 算术运算符:+,-,*,/,%,++,--

    • b=a++;先给b赋值,再自增
      • a=1;b=a++;b=a;a=a+1;a=2;b=1;
    • c=++a;先自增,再给c赋值
      • a=1;c=++a;a=a+1;c=a;a=2;c=2;
    • 很多运算使用工具类去操作
      • 幂运算:2^3→double pow = Math.pow(2,3);
  • 赋值运算符:=

  • 关系运算符:>,<,>=,<=,==,!=,instanceof

  • 逻辑运算符:&&,||,!

    • 与(and) 或(or) 非(取反)

      boolean a=true;
      boolean b=false;
      boolean c1=a&&b;	//false
      boolean c2=a||b;	//true
      boolean c3=!(a&&b);	//true
      
    • 短路运算: && ||

      m=1;n=2;
      // &&:一个为false,结果就为false
      boolean p=(m>2)&&(n<3);	// 根据(m>2)就能得到false结果,后面(n<3)不会执行
      // ||:一个为true,结果就为true
      boolean q=(m<2)||(n<3);	// 根据(m<2)就能得到true结果,后面(n<3)不会执行
      
  • 位运算符:&,|,^,~,>>,<<,>>>(了解!!!)

    A = 0011 1100
    B = 1010 0101
    ---------------
    A&B = 0010 0100
    A|B = 1011 1101
    A^B = 1001 1001
    ~B = 0101 1010
    
    2*8=16 → 2*2*2*2 → 2<<3
    效率极高!!!
    <<	*2
    >>	/2
    0000 0000	0
    0000 0001	1
    0000 0010	2
    0000 0011	3
    0000 0100	4
    0000 1000	8
    0001 0000	16
    
  • 条件运算符:? :

    //三元运算符:
    x ? y : z
    如果x==true,结果为y
    如果x=false,结果为z
    
  • 扩展赋值运算符:+=,-=,*=,/=

    a+=b; //→ a=a+b
    a-=b; //→ a=a-b
    a*=b; //→ a=a*b
    a/=b; //→ a=a/b
    
  • 字符串连接符:+

    a=555;b=999;
    System.out.println(""+a+b);//出现String类型后,前后全部转换成String类型,然后进行运算
    
6、包机制、JavaDoc
包机制
  • 为了更好的组织类,Java提供了包机制,用于区别类名的命名空间

  • 包语句的语法格式为:

    • package pkg1[.pkg2[.pkg3...]];
  • 一般利用公司域名倒置作为包名

  • 为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。使用import语句可完成此功能

    • import package1[.package2[.package3...]].(classname|*); *→通配符
  • 阿里巴巴Java开发手册(全册四版)

  • 阿里巴巴JAVA开发手册.pdf

JavaDoc
  • javadoc用来生成自己的API文档

    • 参数信息

      • @author 作者名

      • @version 版本号

      • @since 指明需要最早使用的jdk版本

      • @param 参数名

      • @return 返回值情况

      • @throws 异常抛出情况

  • jdk帮助文档

  • 通过命令行生成JavaDoc文档:javadoc 参数设置 Java文件

    • .java类名右键Open InExplore复制目录

      • 打开cmd命令:(属性-字体-调大小)

      • 切换目录:cd /d 上面复制的目录

      • javadoc -encoding UTF-8 -charset UTF-8 Doc.java

JavaDoc作业:
  • 查找并学会如何使用IDEA生成JavaDoc文档! 面向百度编程!

    • .java类名右键Open InExplore复制目录

      • 切换到.java类名所在目录

      • javadoc -encoding UTF-8 -charset UTF-8 Tang.java

Java流程控制

1、用户交互Scanner
Scanner对象
  • 类型不能是char类型,具体类型看源码

  • 实现程序和人的交互,我们可以获取用户的输入。java.util.Scanner是Java5的新特性,我们可以通过Scanner类来获取用户的输入。

  • 基本语法:

    Scanner s = new Scanner(System.in);
    
  • 通过 Scanner 类的 next()nextLine() 方法获取输入的字符串,在读取前我们一般需要使用 hasNext()hasNextLine() 判段是否还有输入的数据

    public static void main(String[] args) {
    	//创建一个扫描器对象,用于接收键盘数据
        System.out.println("请输入内容:");
    	Scanner scanner = new Scanner(System.in);
    
    	//------------------1------------------
    	String str = scanner.next();
        System.out.println("输出的内容为:"+str);
    
    	//------------------2------------------
    	// 1→→ 使用next方式接收,判断用户有没有输入字符串
    	if (scanner.hasNext()){
            System.out.println("使用next方式接收:");
    		//使用next方式接收
    		String str = scanner.next();
    		System.out.println("输出的内容为:"+str);
    	}
    
    	//------------------3------------------
    	// 2→→ 使用nextLine方式接收,判断用户有没有输入字符串
    	if (scanner.hasNextLine()){
            System.out.println("使用nextLine方式接收:");
    		//使用nextLine方式接收
    		String str = scanner.nextLine();
    		System.out.println("输出的内容为:"+str);
    	}
    
    	//凡是属于IO流的类如果不关闭会一直占用资源,要养成习惯用完就关掉
    	scanner.close();
    }
    
  • next():

    • 一定要读取到有效字符后才可以结束输入

    • 对输入有效字符之前遇到的空白,next() 方法会自动将其去掉

    • 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符

    • next() 不能得到带有空格的字符串

  • nextLine():

    • 以Enter为结束符,也就是说 nextLine() 方法返回的是输入回车之前的所有字符

    • 可以获得空白

      public static void main(String[] args) {
      	Scanner scanner = new Scanner(System.in);
      	
      	//从键盘接收数据
      	float f = 0.0f;
      	System.out.println("请输入数据:");
      	
      	if (scanner.hasNextFloat()){
      		i = scanner.nextFloat();
      		System.out.println("小数数据:" + i);
      	}else {
      		System.out.println("输入的不是小数数据!")
      	}
      	scanner.close();
      }
      
题目
  • 我们输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束输入并输出执行结果

    • 方法一:这个方法更好

      public static void main(String[] args) {
          double sum = 0; //统计数据总和
          int i = 0; //统计数据个数
          System.out.println("请输入数据:");
          //从键盘接收数据
          Scanner scanner = new Scanner(System.in);
          //通过循环判断是否输入数据,并统计总和和平均数
          while (scanner.hasNextDouble()){
              i++;
              sum = sum + scanner.nextDouble();
              //System.out.println("请输入数据:");
          }
          System.out.println(i+"个数的总和为:" + sum);
          System.out.println(i+"个数的平均数是:" + (sum/i));
          //关闭IO资源
          scanner.close();
      }
      
    • 方法二:

      public static void main(String[] args) {
      	double sum = 0; //计算数据总和
      	int i = 0; //计算输入数据
      	while(true){
              System.out.println("请输入数据:");
              //从键盘接收数据
              Scanner scanner = new Scanner(System.in);
              if (scanner.hasNextDouble()){
                  i++;
      			sum = sum + scanner.nextDouble();
      		}else {
                  scanner.close();
                  break; //跳出循环
              }
          }
          System.out.println("输入了"+i+"个数据,总和:" + sum);
          System.out.println("输入了"+i+"个数据,平均数:" + (sum/i));
      }
      
2、顺序结构
  • Java的基本结构就是顺序结构,除非特别指明,否者就按照顺序一句一句执行

  • 顺序结构是最简单的算法结构

  • 语句与语句之间是按照从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构

3、选择结构
if单选择结构
  • if(布尔表达式){//如果布尔表达式为true将执行的语句}

  • equals:判断字符串是否相等"b".equals("b")

if双选择结构
if(布尔表达式){
	//如果布尔表达式为true将执行的语句
}else{
    //如果布尔表达式为false将执行的语句
}
if多选择结构
if(布尔表达式 1){
	//如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
    //如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
    //如果布尔表达式 3的值为true执行代码
}else{
    //如果以上布尔表达式都不为true执行代码
}
//---------成绩分ABCD..等级---------
public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);

    System.out.println("请输入成绩:");
    int score = scanner.nextInt();
	//判断成绩等级
    if (score == 100) {
        System.out.println("恭喜满分");
    }else if (score<100 && score>=90) {
        System.out.println("A级");
    }else if (score<90 && score>=80) {
        System.out.println("B级");
    }else if (score<80 && score>=70) {
        System.out.println("C级");
    }else if (score<70 && score>=60) {
        System.out.println("D级");
    }else if (score<60 && score>=0) {
        System.out.println("不及格");
    }else {
        System.out.println("成绩不合法");
    }
}
嵌套的if结构
if(布尔表达式 1){
	//如果布尔表达式 1的值为true执行代码
	if(布尔表达式 2){
		//如果布尔表达式 2的值为true执行代码
	}
}
switch多选择结构
  • 多选择结构 switch case 语句

  • switch case语句判断一个变量与一系列值中某个值是否相等,每个值成为一个分支,匹配具体值

    switch (expression){
        case value:
            //语句
            break; //可选
        case value:
            //语句
            break; //可选
        ...	...
    	default: //可选
            //语句
    }
    //---------成绩分ABCDE等级---------
    public static void main(String[] args) {
    
        char grade = 'B';
    
        switch (grade){
            case 'A':
                System.out.println("优秀");
                break;
            case 'B':
                System.out.println("良好");
                break;
            case 'C':
                System.out.println("中等");
                break;
            case 'D':
                System.out.println("及格");
                break;
            case 'E':
                System.out.println("不及格");
                break;
            default:
                System.out.println("未知等级");
        }
    }
    //---------成绩分ABCDE等级---------
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
    
        System.out.println("请输入成绩:");
        int score = scanner.nextInt();
    	//判断成绩等级
        if(score<0){
            System.out.println("成绩不合法");
        }
        switch (score/10){
            case 10:
                System.out.println("恭喜满分");
                break;
            case 9:
                System.out.println("A级");
                break;
            case 8:
                System.out.println("B级");
                break;
            case 7:
                System.out.println("C级");
                break;
            case 6:
                System.out.println("D级");
                break;
            case 5,4,3,2,1,0:
    			System.out.println("不及格");
                break;
        }
    }
    
  • switch语句中的变量类型可以是

    • byte,short,int或者char

    • 从 JavaSE7 开始,switch 支持 String 类型了

      • // 反编译 java---class(字节码文件)----反编译(IDEA)

        • IDEA 反编译需要同意权限 settingpluginsJava Bytecode Decompiler

        • 打开java文件的目录:右键Open InExplore

        • 找到class文件:FlieProject StructureProject复制文件目录找到目录找到class文件

        • 把class文件复制到java同级目录→IDEA中查看

    • 同时case标签必须为字符串常量或字面量

4、循环结构
while循环
  • 先判断后执行

  • 结构:while(布尔表达式){//循环内容}

  • 只要布尔表达式为true,循环会一直进行下去,大多数情况下需要让循环停下来

  • 少数需要循环一直进行下去,比如服务器的请求响应监听等

    while(true){
        //等待客户端连接
        //定时检查
        //。。。。
    }
    
  • 思考:1+2+3+4+…+100=?

    public static void main(String[] args) {
        int i=1;
        int sum=0;
        while(i<=100){
            sum+=i;
            i++;
        }
        System.out.println(sum);
    }
    
do…while循环
  • 先执行后判断

  • 循环先执行一次后判断布尔表达式,至少执行一次

    do {
    	//循环内容
    }while(布尔表达式);
    
for循环
  • for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构

  • for循环执行的次数在执行前就确定了。语法格式:

    • for(初始化;布尔表达式;更新){//代码语句}

    • 死循环:for(;;){}

  • 练习:计算0到100之间的奇数和偶数的和

    public static void main(String[] args) {
        int oddSum=0;//奇数和
        int evenSum=0;//偶数和
        //奇数和
        for (int i = 1; i < 100; i=i+2) {
            oddSum+=i;
        }
        //偶数和
        for (int i = 2; i <= 100; i=i+2) {
            evenSum+=i;
        }
        //奇数和、偶数和
        for (int i = 0; i <= 100; i++) {
            if (i%2!=0) {
                oddSum+=i;//奇数和
            }else {
                evenSum+=i;//偶数和
            }
        }
        System.out.println("奇数和:"+oddSum);
        System.out.println("偶数和:"+evenSum);
    }
    
  • 练习2:用while或for循环输出1-10000之间能被5整除的数,并且每行输出3个

    public static void main(String[] args) {
        //方法一:
        for (int i = 0; i <= 1000; i++) {
            if (i%5==0) {
                System.out.print(i+"\t");
            }
            if (i%(5*3)==0) {
                System.out.println();
            }
        }
        //方法二:
        for (int i = 5,n=1; i <= 1000; i=i+5,n++) {
            if (n%3!=0) {
                System.out.print(i+"\t");
            }else {
                System.out.println(i);
            }
        }
        System.out.println("\n"+"--------------");
    }
    
  • 练习3:打印九九乘法表

    public static void main(String[] args) {
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.print(j+"*"+i+"="+(i*j)+"\t");
            }
            System.out.println();
        }
    }
    
  • 在Java5中引入了一种主要用于数组的增强型for循环

增强for循环
  • Java5引入了一种主要用于数组或集合的增强型for循环

  • Java增强for循环语法格式:

    • for(声明语句:表达式){//代码语句}

    • 声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等

    • 表达式:表达式是要访问数组名,或者是返回值为数组的方法

      public static void main(String[] args) {
          //定义一个数组
          int[] numbers={2,4,6,7};
          //遍历数组的元素
          for (int n : numbers) {
              System.out.println(n);
          }
      }
      
5、break & continue
  • break在任何循环语句的主体部分,均可用break控制循环的流程,break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)

  • continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定

  • 关于goto关键字

    • goto关键字很早就在程序设计语言中出现,尽管goto仍是Java的保留字,但并未在语言中得到正式使用;Java没有goto,然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子---带标签的break和continue

    • “标签”是指后面跟一个冒号的标识符,例如:label:

    • 对Java来说唯一用到标签的地方是循环语句之前,而在循环语句之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方

    • 打印101-150之间所有的质数

      outer://标签:给循环起名字
      for(int i=101;i<=150;i++){
          for(int j=2;j<i/2;j++){
              if(i%j==0){
                  continue outer;
              }
          }
          System.out.print(i+" ");
      }
      
6、练习
  • 打印三角形

    public static void main(String[] args) {
        int n=5; //行数
        for (int i = 1; i <= n; i++) {
            for (int j = n; j >= i; j--) {
                System.out.print("#");
            }
            for (int j = 1; j <= i; j++) {
                System.out.print("*");
            }
            for (int j = 1; j < i; j++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
    

Java方法详解

1、何谓方法
  • System.out.println(),那么它是什么呢?

  • Java方法是够的集合,它们在一起执行一个功能

    • 方法是解决一类问题的步骤的有序组合

    • 方法包含于类或对象中

    • 方法在程序中被创建,在其他地方被引用

  • 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成1个功能,这样利于我们后期的扩展

  • 回顾:方法的命名规则?小驼峰规则

2、方法的定义及调用
方法的定义
  • 方法包含一个方法头和一个方法体

    修饰符 返回值类型 方法名(参数类型 参数名){
        ...
        方法体
        ...
        return 返回值;
    }
    
  • 修饰符:可选,告诉编译器如何调用该方法,定义了该方法的访问类型

  • 返回值类型:void,int,String。。。

  • 方法名:方法的实际名称

  • 参数类型:参数像是一个占位符,参数列表是指方法的参数类型、顺序、参数个数

    • 形式参数:在方法被调用时用于接收外界输入的数据

    • 实参:调用方法时实际传给方法的数据

  • 方法体:方法体包含具体的语句,定义该方法的功能 return→终止方法

    public class Tang {
        public static void main(String[] args) {
            System.out.println(max(5,9));
        }
        public static int max(int num1,int num2){
            return num1>num2?num1:num2;
        }
    }
    
方法调用
  • 调用方法:对象名.方法名(实参类表)

  • Java支持两种调用方法的方式,根据方法 是否返回值来选择

  • 当方法返回一个值的时候,方法调用通常被当作一个值。例如:

    int larger = max(30,40);

  • 如果方法返回值是void,方法调用一定是一条语句

    System.out.println("Hello,TangGuo");

  • 课后拓展了解:值传递(Java)和 引用传递

3、方法重载
  • 同名不同参

    • 方法名称必须相同

    • 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同)

    • 方法的返回类型可以相同也可以不同

    • 仅仅返回类型不同不足以成为方法的重载

  • 实现理论

    • 方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错
4、命令行传参
  • 有时候你希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main()函数实现

    package tang;
    
    public class Tang {
        public static void main(String[] args) {
            //args.length 数组长度
            for (int i = 0; i < args.length; i++) {
                System.out.println("args["+i+"]:"+args[i]);
            }
        }
    }
    
    • 在cmd/Terminal命令窗口运行:

      • PS D:\IT\JavaSE-狂神说\基础语法> cd src/tang

      • PS D:\IT\JavaSE-狂神说\基础语法\src\tang> javac Tang.java //编译.java文件

      • PS D:\IT\JavaSE-狂神说\基础语法\src\tang> cd .. //返回src目录

      • PS D:\IT\JavaSE-狂神说\基础语法\src> java tang.Tang hello tangguo //运行:包名.类名

        args[0]:hello
        args[1]:tangguo
        
5、可变参数
  • JDK1.5开始,Java支持传递同类型的可变参数给一个方法

  • 在方法声明中,在指定参数类型后加一个省略号(...)

  • 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数,任何普通的参数必须在它之前声明

    public class Tang {
        public static void main(String[] args) {
            //调用可变参数的方法
            printMax(3,5,16,87,43,9);
        }
        public static void printMax(double... numbers) {
            if(numbers.length==0){
                System.out.println("No argument passed");
                return;
            }
    
            double result = numbers[0];
    
            //排序
            for (int i = 1; i < numbers.length; i++) {
                result = result > numbers[i] ? result : numbers[i];
            }
            System.out.println("The max value is "+result);
        }
    }
    
6、递归
  • A方法调用B方法,很容易理解

  • 递归就是:A方法调用A方法!就是自己调用自己

  • 利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合

  • 递归结构包括两个部分:

    • 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环

    • 递归体:什么时候需要调用自身方法

      public class Tang {
          public static void main(String[] args) {
              //递归思想
              System.out.println(f(5));
          }
          //递归
          public static long f(int n) {
              if (n == 0||n==1) {
                  return 1;
              }else if (n>=2){
                  return n*f(n-1);
              }else {
                  return -1;
              }
          }
      }
      
作业
  • 写一个计算器,要求实现加减乘除功能,并且能够循环接收新的数据,通过用户交互实现

  • 思路推荐:

    • 写4个方法:加减乘除

    • 利用循环+switch进行用户交互

    • 传递需要操作的两个数

    • 输出结果

      public static void main(String[] args) {
          Scanner scanner = new Scanner(System.in);
          System.out.println("输入第一个数字:");
          int num1 = scanner.nextInt();
          System.out.println("输入一个运算符:");
          String operator = scanner.next();
          System.out.println("输入第二个数字:");
          int num2 = scanner.nextInt();
          switch (operator){
              case "+":
                  System.out.println(num1+"+"+num2+"="+(num1+num2));
                  break;
              case "-":
                  System.out.println(num1+"-"+num2+"="+(num1-num2));
                  break;
              case "*":
                  System.out.println(num1+"*"+num2+"="+(num1*num2));
                  break;
              case "/":
                  System.out.println(num1+"/"+num2+"="+(num1/num2));
                  break;
          }
      }
      

Java数组

1、数组概述
数组的定义
  • 数组是相同类型数据的有序集合

  • 描述相同类型的若干个数据,按照一定的先后次序排列组合而成

  • 每个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们

2、数组声明创建
数组声明创建
  • 首先必须声明数组变量,才能在程序运行中使用数组,下面是声明数组变量的语法:

    dataType[] arrayRedVar;	//首选方法
    或
    dataType arrayRedVar[];	//效果相同,但不是首选方法
    
  • Java语句使用new操作符来创建数组,语法如下:

    dataType[] arrayRedVar = new dataType[arraySize];
    
  • 数组的元素是通过索引访问的,数组索引从0开始

  • 获取数组长度:arrays.length

    public static void main(String[] args) {
        int[] nums;	//声明一个数组
        nums = new int[5];	//创建一个数组
        //给数组中元素赋值
        nums[0] = 1;
        nums[1] = 2;
        nums[2] = 3;
        nums[3] = 4;
        nums[4] = 5;
        System.out.println(nums[0]);
    }
    
内存分析

Java内存分析

  • 写代码画图分析内存

    • 方法区:包含所有的class和static变量,方法本身

    • 栈区:数组名是引用放到栈区,基本类型放到栈区,栈数据共享

    • 堆区:放new的对象和数组

三种初始化
  • 静态初始化:创建 + 赋值

    int[] a = {1,2,3};
    Man[] mans = {new Man(1,1),new Man(2,2)}
    
  • 动态初始化:包含默认初始化

    int[] a = new int[2];
    a[0]=1;
    a[1]=2;
    
  • 数组的默认初始化

    • 数组的引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化
数组的四个基本特点
  • 长度确定,数组一旦被创建,它的大小就不可以改变

  • 一个数组中元素类型必须相同,不允许出现混合类型

  • 数组的元素类型可以是任何数据类型,包括基本类型和引用类型

  • 数组变量属于引用类型,数组也可以看成对象,数组中的每个元素相当于该对象的成员变量

  • 数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始(基本)类型还是其他对象类型,数组对象本身是在堆中的

数组边界
  • 下标的合法区间:[0,length-1],如果越界就会报错

    public static void main(String[] args) {
        int[] a=new int[2];
        System.out.pringln(a[2]);
    }
    
    • java.lang.ArrayIndexOutOfBoundsExceptional:数组下标越界异常!
  • 小结:

    • 数组是相同数据类型的有序集合

    • 数组也是对象,数组元素相当于对象的成员变量

    • 数组长度是确定的,不可变的。如果越界,则报:ArrayIndexOutOfBoundsExceptional

异常情况
  • java.lang.ArrayIndexOutOfBoundsExceptional:数组下标越界异常
3、数组使用
  • 普通for循环:使用最频繁

  • For-Each循环

    //JDK1.5新增功能,获取不了下标
    for(int array : arrays) {
        System.out.println(array);
    }
    
  • 数组作为方法的参数

    public class Tang {
        public static void main(String[] args) {
            int[] arrays={1,2,3,4,5};
            //打印数组元素
            printArrays(arrays);
        }
        //打印数组元素
        public static void printArrays(int[] arrays) {
            for (int i = 0; i < arrays.length; i++) {
                System.out.print(arrays[i]+" ");
            }
            System.out.println();
        }
    }
    
  • 数组作返回值

    public class Tang {
        public static void main(String[] args) {
            int[] arrays={1,2,3,4,5};
            //反转数组
            int[] reverse = reverse(arrays);
        }
        //反转数组
        public static int[] reverse(int[] arrays) {
            int[] result = new int[arrays.length];
            // 反转的操作
            for (int i=0,j = result.length-1; i < arrays.length; i++,j--) {
                result[j] = arrays[i];
            }
            return result;
        }
    }
    
4、多维数组
  • 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组

  • 二维数组

    • int a[][]=new int[2][5];

      public static void main(String[] args) {
          int[][] arrays={{1,2}, {2,3}, {3,4}, {4,5}, {5,6}};
          //打印数组元素
          for (int i = 0; i < arrays.length; i++) {
              for (int j = 0; j < arrays[i].length; j++) {
                  System.out.print(arrays[i][j]+" ");
              }
              System.out.println();
          }
      }
      
  • 解析:以上二维数组a可以看成一个两行五列的数组

  • 思考:多维数组的使用?

    • num[1][0];
5、Arrays类
  • 数组的工具类java.util.Arrays

    //打印数组元素
    System.out.println(Arrays.toString(a));
    //数组排序:升序,小→大
    Arrays.sort(a);
    //数组赋值:数组名,开始下标,结束下标(不包括),填充的值
    Arrays.fill(a,2,6,4);//赋值的下标范围[2,6)
    //数组赋值:
    Arrays.fill(a,4);//全部元素进行赋值
    //比较数组元素;全部相同为:true,否则为:false
    Arrays.equals(a, b);//比较数组全部元素
    Arrays.equals(a,2,5,b,2,5);//比较的下标范围[2,5)
    //排序数组进行二分查找:通过binarySearch方法能对
    Arrays.binarySearch(a,78);//整体查找元素
    Arrays.binarySearch(a,2,6,78);//查找的下标范围[2,5)
    
  • API提供了一个工具类Arrays供我们使用

  • 查看JDK帮助文档

  • Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,儿“不用”使用对象来调用(注意:是“不用”而不是”不能“)

  • 具有以下常用功能:

    • 给数组赋值:通过fill方法

    • 对数组进行排序:通过sort方法,按照升序

    • 比较数组:通过equals方法比较数组中元素是否相等

    • 查找数组元素:通过binarySearch方法能对排序数组进行二分查找法操作

冒泡排序
  • 冒泡排序最为出名的排序算法之一,共有八大排序

  • 冒泡排序代码:两层循环,外层冒泡轮数,里层依次比较

    //依次比较两个元素,选出最小或最大的数字,放到后面
    public static void main(String[] args) {
        int[] a={98,544,665,78,334,43,78,35};
        //大的往后放
        //判断要走a.length-1次
        for (int i = 0; i < a.length-1; i++) {
            boolean flag = false;//通过flag标识位减少没有意义的比较
            //内层循环,比较两个数,大的放后面
            for (int j = 1; j < a.length-i; j++) {
                if(a[j-1]>a[j]){
                    int temp=a[j-1];//临时变量
                    a[j-1]=a[j];
                    a[j]=temp;
                }
            }
            if (!flag){
                break;
            }
        }
        System.out.println(Arrays.toString(a));
    }
    
  • 看到嵌套循环,应该马上就可以的得出这个算法的时间复杂度为O(n2)

  • 思考:如何优化

    • 通过flag标识位减少没有意义的比较
6、稀疏数组
  • 需求:编写五子棋游戏中,有存盘退出和续上盘的功能

  • 分析问题:因为该二维数组的很多值是默认值0,因此记录了很多没有意义的数据

  • 解决:稀疏数组

    public static void main(String[] args) {
        //创建一个二维数组 11 * 11    0:没有棋子,   1:黑棋,   2:白棋
        int[][] array1=new int[11][11];
        array1[1][2]=1;
        array1[2][3]=2;
        //输出原始的数组
        System.out.println("输出原始的数组:");
        for (int[] ints : array1) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }
        System.out.println("================");
        //转换为稀疏数组保存
        //获取有效值的个数
        int sum=0;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if(array1[i][j]!=0){
                    sum++;
                }
            }
        }
        System.out.println("有效值的个数:"+sum);
    
        //创建一个稀疏数组
        int[][] array2 = new int[sum+1][3];
    
        array2[0][0]=11;
        array2[0][1]=11;
        array2[0][2]=sum;
    
        //遍历二维数组,将非零的值,存放在稀疏数组中
        int count=0;
        for (int i = 0; i < array1.length; i++) {
            for (int j = 0; j < array1[i].length; j++) {
                if(array1[i][j]!=0){
                    count++;
                    array2[count][0] = i;
                    array2[count][1] = j;
                    array2[count][2] = array1[i][j];
                }
            }
        }
        //输出稀疏数组
        System.out.println("稀疏数组:");
        for (int i = 0; i < array2.length; i++) {
            for (int j = 0; j < array2[i].length; j++) {
                System.out.print(array2[i][j]+"\t");
            }
            System.out.println();
        }
        System.out.println("================");
        System.out.println("还原:");
        //1.读取稀疏数组
        int[][] array3 = new int[array2[0][0]][array2[0][1]];
        //2.还原元素的值
        for (int i = 1; i < array2.length; i++) {
            array3[array2[i][0]][array2[i][1]] = array2[i][2];
        }
        //3.打印
        for (int[] ints : array3) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }
    }
    
稀疏数组介绍
  • 当一个数组中大部分元素为0,或者为同一值的数组时,可以使用系数数组来保存该数组

  • 稀疏数组的处理方式是:

    • 记录数组一共有几行几列,有多少个不同值

    • 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模

  • 下图:左边是原始数组,右边是稀疏数组

    row col value
    0 0 3 0 [0] 5 4 4
    0 0 0 0 [1] 0 2 3
    0 5 0 0 [2] 2 1 5
    0 0 2 0 [3] 3 2 2
    0 1 0 0 [4] 4 1 1

面向对象编程

  • Java的核心思想就是OOP面向对象编程
1、初始面向对象
面向过程 & 面向对象
  • 面向过程思想

    • 步骤清晰简单,第一步做什么,第二步做什么……

    • 面向过程的适合处理一些较为简单的问题

  • 面向对象思想

    • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索

    • 面向对象适合处理复杂的问题,适合处理需要多人协作的问题

  • 对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理

什么是面向对象
  • 面向对象编程(Object-Oriented Programming,OOP)

  • 面向对象编程的本质就是:以类的方法组织代码,以对象的方式组织(封装)数据

  • 抽象:编程思想!持续的学习,茅塞顿开!多实践,多测试大脑中的想法!实践出真知~

  • 抽象

  • 三大特性:

    • 封装

    • 继承

    • 多态

  • 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象

  • 从代码运行角度考虑是现有类后有对象。类是对象的模板

2、方法回顾和加深
  • 方法的定义

    • 修饰符

    • 返回类型

    • break:跳出switch,结束循环;return:结束方法

    • 方法名:注意规范就OK 见名知意

    • 参数列表:(参数类型,参数名)...

    • 异常抛出:疑问,后面讲解

  • 方法的调用:递归

    • 静态方法

      public static void a() {};//和类一起加载
      
    • 非静态方法

      public void b() {};//类实例化之后才存在
      
    • 形参和实参

    • 值传递和引用传递

      • 基本类型:值传递

      • 引用传递:对象,本质还是值传递

    • this关键字

3、对象的创建分析
类与对象的关系
  • 类是以一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物

  • 对象是抽象概念的具体实例

创建和初始化对象
  • 使用new关键字创建对象

    //学生类
    public class student {
        //属性:字段
        String name; //null
        int age; //0
        //方法
        public void study(){
            System.out.println(this.name+"在学习");
        }
    }
    //测试类:一个项目应该只存一个main方法
    public class application {
        public static void main(String[] args) {
            //类:抽象的,实例化
            //类实例化后会返回一个对象
            //student对象就是Student类的一个具体实例
            student xm = new student();
            xm.name="小明"; //名字
            xm.age=18; //年龄
            System.out.println(xm.name);
            System.out.println(xm.age);
        }
    }
    
  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用

  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的,并且构造器有以下两个特点:

    public class Person {
        //一个类即使什么都不写,它也会存在一个方法
        //显示的定义构造器
        String name;
        //1.使用new关键字,本质是在调用构造器
        //2.用来初始化值
        public Person(){
            this.name="糖果"; //实例化初始值
        }
        //有参构造:一旦构造了有参构造,无参构造就必须显示定义
        public Person(String name){
            this.name=name;
        }
    }
    //测试类:一个项目应该只存一个main方法
    public class application {
        public static void main(String[] args) {
            //实例化了一个对象
            Person person = new Person();
            System.out.println(person.name);
        }
    }
    
    • 构造器:

      • 1.必须和类的名字相同

      • 2.必须没有返回类型,也不能写void

    • 作用:

      • 1.new 本质在调用构造器

      • 2.初始化对象的值

    • 注意点:

      • 定义有参构造后,如果要使用无参构造,必须要显示的定义一个无参构造
  • 构造器必须要掌握

  • 简单内存分析

    public class Pet {
        //一个类即使什么都不写,它也会存在一个方法
        //显示的定义构造器
        String name;
        int age;
        public void shout() {
            System.out.println("叫一声");
        }
    }
    //测试类:一个项目应该只存一个main方法
    public class application {
        public static void main(String[] args) {
            //创建对象dog
            Pet dog = new Pet();
            dog.name="旺财";
            dog.age=3;
            dog.shout();
            System.out.println(dog.name);
            System.out.println(dog.age);
            //创建对象cat
            Pet cat = new Pet();
        }
    }
    

简单内存分析

小结:
  1. 类与对象

    • 类是模板:抽象,对象是一个具体的实例
  2. 方法

    • 定义,调用!
  3. 对象的引用

    • 引用类型:基本类型(8)

    • 对象是通过引用来操作的:栈--->堆

  4. 属性:字段Field成员变量

    • 默认初始化:

      • 数字:0 0.0

      • char:u0000

      • boolean:false

      • 引用:null

    • 修饰符 属性类型 属性名 = 属性值!

  5. 对象的创建和使用

    • 必须使用new关键字创造对象,构造器 Person tangGuo = new Person();

    • 对象的属性 tangGuo.name;

    • 对象的方法 tangGuo.sleep();

    • 静态的属性 属性

    • 动态的行为 方法

4、面向对象三大特性
封装
  • 该露的露,该藏的藏

    • 我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用
  • 封装(数据的隐藏)

    • 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏
  • 记住这句话就够了:属性私有,get/set

    //类 private:私有
    public class Student {
        //属性私有
        private String name; //名字
        private int id; //学号
        private char gender; //性别
        private int age; //年龄
        //提供一些可以操作这个属性的方法!
        //提供一些public的get、set方法
        //get 获得这个数据
        public String getName() {return this.name;}
        //set 给这个数据设置值
        public void setName(String name) {this.name = name;}
        public int getId() {return id;}
        public void setId(int id) {this.id = id;}
        public char getGender() {return gender;}
        public void setGender(char gender) {this.gender = gender;}
        public int getAge() {return age;}
        public void setAge(int age) {
            if (age>150||age<0) {
                this.age = -1;
            }else {
                this.age = age;
            }
        }
    }
    //测试类:一个项目应该只存一个main方法
    public class application {
        public static void main(String[] args) {
            Student s1 = new Student();
            s1.setName("糖果"); //设置名字
            System.out.println(s1.getName());
            s1.setAge(999); //设置年龄
            System.out.println(s1.getAge());
        }
    }
    
  • 封装的意义

    • 提供程序的安全性,保护数据

    • 隐藏代码的实现细节

    • 统一接口

    • 提高了系统的可维护性

继承
  • 继承的本质是对某一批的抽象,从而实现对现实世界更好的建模

  • extands的意思是“扩展”。子类是父类的扩展

    • Java中,所有的类,都默认直接或间接继承Object类

    • Ctrl+H:继承树

    • private修饰无法被继承

    • public,protected,[default],private

  • JAVA中类只有单继承,没有多继承

  • 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等

  • 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示

  • 子类和父类之间,从意义上讲应该具有“is a”的关系

  • object类

    • Java中,所有的类,都默认直接或间接继承Object类
  • super - this

    • 私有的东西无法被继承

      //属性调用
      public class Person {
          protected String name = "人类";
      }
      //学生 is 人:派生类,子类
      //子类继承了父类,就会拥有父类的全部方法!
      public class Student extends Person{
          private String name = "糖果";
          public void test(String name){
              System.out.println(name); //甜甜→方法中的
              System.out.println(this.name); //糖果→子类的
              System.out.println(super.name); //人类→父类的
          }
      }
      //测试类:一个项目应该只存一个main方法
      public class application {
          public static void main(String[] args) {
              Student s1 = new Student();
              s1.test("甜甜");
          }
      }
      
      //方法调用
      public class Person {
          protected void print(){
              System.out.println("Person");
          }
      }
      public class Student extends Person{
          public void print(){
              System.out.println("Student");
          }
          public void test(){
              print(); //Student:调子类方法
              this.print(); //Student:调子类方法
              super.print(); //Person:调父类方法
          }
      }
      //测试类:一个项目应该只存一个main方法
      public class application {
          public static void main(String[] args) {
              Student s1 = new Student();
              s1.test();
          }
      }
      
      /构造器调用/
      public class Person {
          public Person(){
              System.out.println("Person无参构造执行了");
          }
      }
      public class Student extends Person{
          public Student() {
              //隐藏代码,调用了父类的无参构造
              super();//调用父类的构造器,必须要在子类构造器的第一行
              System.out.println("Student无参构造执行了");
          }
      }
      //测试类:一个项目应该只存一个main方法
      public class application {
          public static void main(String[] args) {
              Student s1 = new Student();
      
          }
      }
      
    • super注意点:

      1. super调用父类的构造方法,必须在构造方法的第一个
      2. super必须只能出现在子类的方法或者构造方法中
      3. super和this不能同时调用构造方法
    • super和this的比较

      • 代表的对象不同

        • this:调用者本身对象的引用

        • super:代表父类对象的引用

      • 前提

        • this:没有继承也可以使用

        • super:只能在继承条件下才能使用

      • 构造方法

        • this():本类的构造

        • super():父类的构造

  • 方法重写:方法重写必须是非静态的方法

    //父类
    public class A {
        public void test(){
            System.out.println("A.test");
        }
    }
    //子类
    //重写都是方法的重写,和属性无关
    public class B extends A{
        //Override 重写
        @Override //注解:有功能的注释!
        public void test() {
            System.out.println("B.test");
        }
    }
    //测试类:一个项目应该只存一个main方法
    public class application {
        //静态的方法和非静态的方法,区别很大
        //静态方法:方法的调用,只和左边定义的,数据类型相关
        public static void main(String[] args) {
            B b = new B();
            b.test(); //B
            //父类的引用指向了子类
            A a = new B(); //子类重写了父类的方法
            a.test(); //B
        }
    }
    
    • 非静态方法,才能重写

    • 重写:需要有继承关系,子类重写父类的方法!

      1. 方法名必须相同

      2. 参数列表必须相同

      3. 修饰符:范围可以扩大但不能缩小: public > protected > [default] > private

      4. 抛出的异常:范围,可以被缩小但不能被扩大;ClassNotFoundException --> Exception(大)

    • 重写,子类的方法和父类必须要一致,方法体不同!

    • 为什么需要重写:

      • 父类的功能,子类不一定需要,或者不一定满足!
多态
  • 即同一方法可以根据发送对象的不同而采用多种不同的行为方式

  • 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)

  • 多态存在的条件

    • 有继承关系

    • 子类重写父类方法

    • 父类引用指向子类对象

  • 注意:多态是方法的多态,属性没有多态性

    public class Person{
        public void run(){
            System.out.println("Person.run");
        }
    }
    public class Student extends Person{
        @Override
        public void run() {
            System.out.println("Student.run");
        }
        public void eat(){
            System.out.println("Student.eat");
        }
    }
    //测试类:一个项目应该只存一个main方法
    public class application {
        public static void main(String[] args) {
            //一个对象的实际类型是确定的
            //new Student();
            //new Person();
    
            //可以指向的引用类型就不确定了
    
            //Student 能调用的方法都是自己的或者继承父类的!
            Student s1 = new Student();
            //Person 父类型,可以指向子类,但是不能调用子类独有的方法
            Person s2 = new Student();
            //对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
            //s2.eat(); 无法执行eat()方法:左边Person父类没有eat()方法,
            //执行的方法,如果子类进行了重写,将按照子类的执行
            s2.run(); //右边Student子类重写了左边Person父类的run()方法,因此执行右边Student子类的方法体代码
            s1.eat();
        }
    }
    
  • 多态注意事项:

    • 多态是方法的多态,属性没有多态

    • 父类和子类,有联系 类型转换异常! ClassCastException!

    • 存在条件:继承关系,方法需要重写,父类引用指向子类对象! Father f1 = new Son();

    • 以下内容不能重写,没有多态:

      • static 方法,属于类,它不属于实例

      • final 常量

      • private 方法

  • instanceof(类型转换)引用类型,判断一个对象是什么类型~

    //测试类:一个项目应该只存一个main方法
    public class application {
        public static void main(String[] args) {
            //Object>String
            //Object>Person>Teacher
            //Object>Person>Student
            Object object = new Student();
    
            System.out.println(object instanceof Student); //true
            System.out.println(object instanceof Person); //true
            System.out.println(object instanceof Object); //true
            System.out.println(object instanceof Teacher); //false
            System.out.println(object instanceof String); //false
            System.out.println("==========================");
            Person person = new Student();
            System.out.println(person instanceof Student); //true
            System.out.println(person instanceof Person); //true
            System.out.println(person instanceof Object); //true
            System.out.println(person instanceof Teacher); //false
            // System.out.println(person instanceof String); //编译不通过
            System.out.println("==========================");
            Student student = new Student();
            System.out.println(student instanceof Student); //true
            System.out.println(student instanceof Person); //true
            System.out.println(student instanceof Object); //true
            // System.out.println(student instanceof Teacher); //编译不通过
            // System.out.println(person instanceof String); //编译不通过
        }
    }
    
    public static void main(String[] args) {
        A x = new B();
    	System.out.println(x instanceof Y); 
        /*
        	1.A与Y有父子关系才能进行比较(A>=Y||A<=Y),没有父子关系的进行比较编译会报错
        	2.B是Y的子类或本类(B<=Y):结果为true,否则为false
    	*/
    }
    
    • 有父子关系的才能进行比较,没有父子关系的进行比较编译会报错
  • 类型转换

    public static void main(String[] args) {
        //类型之间的转化:  父   子
        //子类型换为父类,可能丢失自己本来的一些方法
        Student student = new Student();
        student.go();
        Person person = student;
        /*
        1. 父类引用指向子类的对象
        2. 把子类转换为父类,向上转型;直接转换,子类独有方法无法调用
        3. 把父类转换为子类,向下转型;强制转换,子类独有方法可以调用
        4. 方便方法的调用,减少重复的代码!简洁
        抽象:     封装、继承、多态!   抽象类,接口
         */
    }
    
static
  • final修饰的类不能被继承
public class Student {
    private static int age; //静态变量  多线程!
    private double score; //非静态变量
    public void run(){} //非静态方法
    public static void go(){} //静态方法
    //1
    static {
        //静态代码块
        System.out.println("静态代码块");
    }
    //2:赋初始值~
    {
        //代码块(匿名代码块),构造器之前调用
        System.out.println("匿名代码块");
    }
    //3
    public Student() {
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        Student student1 = new Student();
        System.out.println("================");
        Student student2 = new Student();
    }
}
//静态导入包~
import static java.lang.Math.PI;
import static java.lang.Math.random;

public class Test {
    public static void main(String[] args) {
        System.out.println(random());
        System.out.println(PI);
    }
}
5、抽象类和接口
抽象类
  • abstract修饰符可以修饰方法和类;被abstract修饰后的方法、类,被称为抽象方法、抽象类

    1. 不能new抽象类,只能靠子类去实现它:约束!

    2. 抽象类中可以写普通方法~

    3. 抽象方法必须在抽象类中~

    4. 抽象的抽象:约束~

    //abstract 抽象类: 类 extends:单继承~      (接口可以多继承)
    public abstract class A {
    
        //约束~有人帮我们实现~
        //abstract,抽象方法,只有方法名字,没有方法的实现!
        public abstract void test();
        public void test1(){}
    }
    //抽象类的所有抽象方法,必须由继承了它的子类去实现~  (如果子类也是抽象类,没有此要求)
    public class B extends A{
        @Override
        public void test() {
        }
    }
    
  • 思考题:

    • 抽象类存在构造器吗?不存在。

    • 抽象类存在的意义:抽象出来~ 提高开发效率

接口
  • 普通类:只有具体实现

  • 抽象类:具体实现和规范(抽象方法)都有!

  • 接口:只有规范!自己无法写方法专业的约束!约束和实现分离:面向接口编程

  • 接口就是规范,定义在一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你是好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。

  • 接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。

  • OO的精髓,是对对象的抽象,最难体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如C++、Java、C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。

  • 声明类的关键字是class,声明接口的关键字是interface

    //抽象的思维~ Java
    //interface 定义的关键字, 接口都需要有实现类
    public interface UserService {
        //属性都是常量, 默认都有:public static final
        int AGE = 99;
        //接口中的所有方法定义都是抽象的, 默认都有:public abstract
        void add(String name);
        void delete(String name);
        void update(String name);
        void query(String name);
    }
    public interface TimeService {
        void timer();
    }
    //抽象类:extends~
    //类 可以实现接口 implements 接口
    //实现了接口的类, 就需要重写接口的方法
    //多继承~利用接口实现多继承~
    public class UserServiceImpl implements UserService,TimeService {
        @Override
        public void add(String name) {}
        @Override
        public void delete(String name) {}
        @Override
        public void update(String name) {}
        @Override
        public void query(String name) {}
        @Override
        public void timer() {}
    }
    
  • 作用:

    1. 约束

    2. 定义一些方法,让不同的人实现~

    3. 方法:默认都有:public abstract

    4. 属性:默认都有:public static final

    5. 接口不能被实例化~,接口中没有构造方法

    6. implements可以实现多个接口

    7. 必须要重写接口中的方法

    8. 接口只能继承一个接口,用extends

    9. 总结博客~

6、内部类及OOP实战
内部类
  • 内部类就是在一个类的内部再定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了
  1. 成员内部类

    public class Outer {
        private int id;
        public void out(){
            System.out.println("这是外部类的方法");
        }
        public class Inner1{
            public void in(){
                System.out.println("这是内部类的方法");
            }
            //获得外部类的私有属性
            public void getId(){
                System.out.println(id);
            }
        }
    }
    //测试类
    public class Application {
        public static void main(String[] args) {
            //new
            Outer outer = new Outer();
            //通过外部类来实例化非静态内部类
            Outer.Inner1 inner1 = outer.new Inner1();
            inner1.getId();
        }
    }
    
  2. 静态内部类

    public class Outer {
        public void out(){
            System.out.println("这是外部类的方法");
        }
        public static class Inner2{
            public void in(){
                System.out.println("这是内部类的方法");
            }
        }
    }
    //测试类
    public class Application {
        public static void main(String[] args) {
            //静态内部类
            Outer.Inner2 inner2 = new Outer.Inner2();
            inner2.in();
        }
    }
    
  3. 局部内部类

    public class Outer {
        public void method(){
            //局部内部类
            class Inner{
                public void in(){}
            }
        }
    }
    
  4. 匿名内部类

    public class Test {
        public static void main(String[] args) {
            //没有名字初始化类, 不用将实例保存到变量中
            new Apple().eat();
            
            UserService userService = new UserService() {
                @Override
                public void hello() {
                    System.out.println("hello");
                }
            };
        }
    }
    class Apple{
        public void eat(){
            System.out.println("1");
        }
    }
    interface UserService{
        void hello();
    }
    

Java异常机制

1、什么是异常
  • 软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是:Exception

  • 异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等

  • 异常发生在程序运行期间,它影响了正常的程序执行流程

简单分类
  • 要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:

    • 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法遇见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略

    • 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略

    • 错误ERROR:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,在编译也检查不到的

  • 异常处理框架

2、异常体系结构
  • Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类

  • 在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception

异常体系结构

Error
  • Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关

  • Java虚拟机运行错误(virtual MachineError),当JVM不再有继续执行所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止

  • 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况

Exception
  • 在Exception分支中有一个重要的子类RuntimeException(运行时异常)

    • ArrayIndexOutOfBoundsException(数组下标越界)

    • NullPointerException(空指针异常)

    • ArithmeticException(算术异常)

    • MissingResourceException(丢失资源)

    • ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理

  • 这些异常一般是有程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生

  • Error和Exception的区别:Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常

3、Java异常处理机制
  • 抛出异常

  • 捕获异常

  • 异常处理五个关键字

    • try、catch、finally、throw、throws
4、处理异常
  • 捕获异常快捷键:Ctrl+Alt+T:try-catch-finally

    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        try { //try监控区域
            System.out.println(a/b);
        }catch (ArithmeticException e){ //catch捕获异常,ArithmeticException想要捕获的异常类型
            System.out.println("程序出现异常,变量b不能为0");
        }finally { //处理善后工作
            System.out.println("finally");
        }
        //finally:可以不要finally(假设IO,资源,关闭!)
    }
    
    public class Test {
        public static void main(String[] args) {
            try { //try监控区域
                new Test().a();
            }catch (Throwable e){ //catch捕获异常,Throwable想要捕获的异常类型
                System.out.println("程序出现异常");
            }finally { //处理善后工作
                System.out.println("finally");
            }
        }
        public void a(){b();}
        public void b(){a();}
    }
    
    public class Test {
        public static void main(String[] args) {
            int a = 1;
            int b = 0;
            //要捕获多个异常: 从小到大!
            try { //try监控区域
                System.out.println(a/b);
            }catch (Error e){ //catch捕获异常
                System.out.println("Error");
            }catch (Exception e){ //catch捕获异常
                System.out.println("Exception");
            }catch (Throwable t){ //catch捕获异常
                System.out.println("Throwable");
            }finally { //处理善后工作
                System.out.println("finally");
            }
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            int a = 1;
            int b = 0;
            try {
                System.out.println(a/b);
            } catch (Exception e) {
                e.printStackTrace(); //打印错误的栈信息
            } finally {
            }
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            try {
                new Test().test(1,0);
            } catch (ArithmeticException e) {
                e.printStackTrace();
            } finally {
            }
        }
        //假设这个方法中,处理不了这个异常。方法上抛出异常
        public void test(int a,int b) throws ArithmeticException{
            if (b==0){ //throw throws
                throw new ArithmeticException(); //主动抛出异常, 一般在方法中使用
            }
            System.out.println(a/b);
        }
    }
    
5、自定义异常
  • 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需要继承Exception类即可

  • 在程序中使用自定义异常类,大体可分为以下几个步骤:

    1. 创建自定义异常类

    2. 在方法中通过throw关键字抛出异常对象

    3. 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throw关键字指明要抛出给方法调用者的异常,继续进行下一步操作

    4. 在出现异常方法的调用者中捕获并处理异常

      //自定义的异常类
      public class MyException extends Exception{
          //传递数字>10;
          private int detail;
          public MyException(int detail) {
              this.detail = detail;
          }
          //toString:异常的打印信息
          @Override
          public String toString() {
              return "MyException{" + detail + '}';
          }
      }
      //测试类
      public class Test {
          //可能会存在异常的方法
          static void test(int a) throws MyException {
              System.out.println("传递的参数为:"+a);
              if (a>10){
                  throw new MyException(a); //抛出
              }
              System.out.println("OK");
          }
          public static void main(String[] args) {
              try {
                  test(99);
              } catch (MyException e) {
                  //增加一些处理异常的代码
                  System.out.println("MyException=>"+e);
              }
          }
      }
      
6、总结
实际应用中的总结
  • 处理运行时异常时,采用逻辑去合理规避同时辅组try-catch处理

  • 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常

  • 对于不确定的代码,可以加上try-catch,处理潜在异常

  • 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出

  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定

  • 尽量添加finally语句块去释放占用的资源,IOScanner

IDEA

IDEA快捷键
  • Atl+Enter:各种错误改善提示

  • Ctrl+。:中文输入法条件下,切换中英文标点符号

  • Ctrl+D:复制当前行到下一行

  • Ctrl+H:继承树

  • Ctrl+Alt+T:捕获异常try-catch-finally

  • 注释

    • Ctrl+/:单行注释

    • Ctrl+Shift+/,/*Enter:多行注释

    • /**Enter:文档注释

  • 快速生成代码

    • 打印后换行:sout:System.out.println();

    • 打印Hello.方法名soutm:System.out.println("Hello.printArrays");

    • for循环

      • arrays.forfor(int array : arrays) {}

      • 10.forifor(int i = 0; i < 10; i++) {}

      • 10.forrfor(int i = 10; i > 0; i--) {}

    • 快速生成构造器:Alt+Insert(右键→Generate)→Constructor

    • 快速生成get……等方法:Alt+Insert(右键→Generate)→。。。

    • 重写方法:Alt+Insert(右键→Generate)→override

IDEA生成JavaDoc文档
  1. 类似cmd生成javadoc文档:使用IDEA生成JavaDoc文档! 面向百度编程!

    • .java类名右键Open InExplore复制目录

      • 切换到.java类名所在目录

      • javadoc -encoding UTF-8 -charset UTF-8 Tang.java

  2. IDEA生成JavaDoc文档

    • ToolsGenerate JavaDoc→设置下面几项

      • Custom scope

      • Output directory。。。

      • Other command line arguments-encoding UTF-8 -charset UTF-8

IDEA反编译
  • // 反编译 java---class(字节码文件)----反编译(IDEA)

    • IDEA 反编译需要同意权限 settingpluginsJava Bytecode Decompiler

    • 打开java文件的目录:右键Open InExplore

    • 找到class文件:FlieProject StructureProject复制文件目录找到目录找到class文件

    • 把class文件复制到java同级目录→IDEA中查看

在线画图

在线画图

posted @ 2022-05-16 23:40  糖果~  阅读(68)  评论(0)    收藏  举报
目录

菜单

展开
深色
fff