java入门

JAVA

HelloWorld

  1. 创建一个文件夹存放代码 /java/code

  2. 新建一个java文件

    • 文件后缀名为.java
    • hello.java
  3. 编写代码

    public class HelloWorld{
    	public static void main(String[] args){
    		System.out.println("Hello World!");
    	}
    }
    
  4. 运行

    C:\Users\Dell>cd D:\3_doc\java\code
    C:\Users\Dell>d:
    D:\3_doc\java\code>javac HelloWorld.java   
    D:\3_doc\java\code>java HelloWorld
    Hello World!
    

JAVA程序运行机制

  • 编译型

  • 解释型

  • 程序运行机制

    image-20221215133710932

IDEA安装

  • 什么是IDE

    集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套。所有具备这一特性的软件或者软件套(组)都可以叫集成开发环境。如微软的Visual Studio系列,Borland的C++ Builder、Delphi系列等。该程序可以独立运行,也可以和其它程序并用。IDE多被用于开发HTML应用软件。例如,许多人在设计网站时使用IDE(如HomeSite、DreamWeaver等),因为很多项任务会自动生成。
    
  • IDEA介绍

    IDEA 全称 IntelliJ IDEA,是java编程语言的集成开发环境。IntelliJ在业界被公认为最好的Java开发工具,尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能可以说是超常的。IDEA是JetBrains公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。它的旗舰版还支持HTML,CSS,PHP,MySQL,Python等。免费版只支持Java,Kotlin等少数语言。
    
  • IDEA官网 JetBrains: Essential tools for software developers and teams

JAVA基础语法

注释

  • 平时我们编写代码,在代码量比较少的时候,我们还可以看懂自己写的东西,但是当项目结构一旦复杂起来,我们就需要用到注释了

  • 注释并不会被执行,是给我们写代码的人看的

  • 书写注释是一个非常好的习惯

  • Java中的注释有三种

    • 单行注释

      public class HelloWorld {
          public static void main(String[] args) {
              //单行注释
              //输出一个HelloWorld
              System.out.println("Hello World");
          }
      }
      
    • 多行注释

      /*
      慈母手中肉
      游子身上膘
      */
      
    • 文档注释

      /**
       * @description
       * @Author goldtree
       */
      
    • 有趣的代码注释

      /***
       *                                         ,s555SB@@&                          
       *                                      :9H####@@@@@Xi                        
       *                                     1@@@@@@@@@@@@@@8                       
       *                                   ,8@@@@@@@@@B@@@@@@8                      
       *                                  :B@@@@X3hi8Bs;B@@@@@Ah,                   
       *             ,8i                  r@@@B:     1S ,M@@@@@@#8;                 
       *            1AB35.i:               X@@8 .   SGhr ,A@@@@@@@@S                
       *            1@h31MX8                18Hhh3i .i3r ,A@@@@@@@@@5               
       *            ;@&i,58r5                 rGSS:     :B@@@@@@@@@@A               
       *             1#i  . 9i                 hX.  .: .5@@@@@@@@@@@1               
       *              sG1,  ,G53s.              9#Xi;hS5 3B@@@@@@@B1                
       *               .h8h.,A@@@MXSs,           #@H1:    3ssSSX@1                  
       *               s ,@@@@@@@@@@@@Xhi,       r#@@X1s9M8    .GA981               
       *               ,. rS8H#@@@@@@@@@@#HG51;.  .h31i;9@r    .8@@@@BS;i;          
       *                .19AXXXAB@@@@@@@@@@@@@@#MHXG893hrX#XGGXM@@@@@@@@@@MS        
       *                s@@MM@@@hsX#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&,      
       *              :GB@#3G@@Brs ,1GM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B,     
       *            .hM@@@#@@#MX 51  r;iSGAM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8     
       *          :3B@@@@@@@@@@@&9@h :Gs   .;sSXH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@:    
       *      s&HA#@@@@@@@@@@@@@@M89A;.8S.       ,r3@@@@@@@@@@@@@@@@@@@@@@@@@@@r    
       *   ,13B@@@@@@@@@@@@@@@@@@@5 5B3 ;.         ;@@@@@@@@@@@@@@@@@@@@@@@@@@@i    
       *  5#@@#&@@@@@@@@@@@@@@@@@@9  .39:          ;@@@@@@@@@@@@@@@@@@@@@@@@@@@;    
       *  9@@@X:MM@@@@@@@@@@@@@@@#;    ;31.         H@@@@@@@@@@@@@@@@@@@@@@@@@@:    
       *   SH#@B9.rM@@@@@@@@@@@@@B       :.         3@@@@@@@@@@@@@@@@@@@@@@@@@@5    
       *     ,:.   9@@@@@@@@@@@#HB5                 .M@@@@@@@@@@@@@@@@@@@@@@@@@B    
       *           ,ssirhSM@&1;i19911i,.             s@@@@@@@@@@@@@@@@@@@@@@@@@@S   
       *              ,,,rHAri1h1rh&@#353Sh:          8@@@@@@@@@@@@@@@@@@@@@@@@@#:  
       *            .A3hH@#5S553&@@#h   i:i9S          #@@@@@@@@@@@@@@@@@@@@@@@@@A.
       *
       *
       *    又看源码,看你妹妹呀!
       */
      

标识符

  • 关键字

    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
  • Java所有的组成部分都需要名字。类名,变量名以及方法名都被称为标识符

  • 标识符注意点

  • 所有的标识符都可以以字幕,美元符或下划线开始
  • 首字母之后可以是字母,美元符,下划线或者数字
  • 不能使用关键字作为变量名或方法名
  • 标识符是大小写敏感的
  • 可以使用中文名,但是一般不用,不要使用拼音,low

数据类型

  • 强类型语言
    • 要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用
  • 弱类型语言
  • Java的数据类型分为两大类
    • 基本类型(primitive type)
    • 引用类型(reference type)

image-20221215154031132

示例

public class demo01 {
    public static void main(String[] args) {
        //整数
        byte num1 = 100;
        short num2 = 10000;
        int num3 = 1000000000; //最常用
        long num4 = 1000000000000L; //LONG类型使用时候用在数字后面用L结尾

        //小数
        float num5 = 100.00F;  //FLOAT类型使用时候用在数字后面用F结尾
        double num6 = 100.00;

        //字符类型
        char name1 = 'A'; //不能用""号
        
        //字符串,string不是关键字,是一个类
        String name2 = "你好";
        
        //布尔值
        boolean flag = true;
        //boolean flag = false;
        
    }

数据类型扩展

public class demo02 {
    public static void main(String[] args) {
        //整数扩展:        进制    二进制0b      十进制             十六进制0x
        int i1 = 10;
        int i2 = 010; //八进制0
        int i3 = 0x61;//十六进制0x

        System.out.println(i1);
        System.out.println(i2);
        System.out.println(i3);
        System.out.println("========================================");
        /*
        =================================================================
        浮点数扩展?  银行业务怎么表示
        BigDecimal  数学工具类
        =================================================================
         */
        //float    长度有限  离散  有舍入误差 接近但不等于
        //double
        //最好避免使用浮点数进行比较!!!
        //最好避免使用浮点数进行比较!!!
        //最好避免使用浮点数进行比较!!!

        float f = 0.1f;
        double d = 1.0/10;
        System.out.println(f==d); //false
        System.out.println(f);
        System.out.println(d);

        float d1 = 23232332323f;
        float d2 = d1 + 1 ;
        System.out.println(d1==d2); //true

        /*
        =================================================================
        字符扩展?
        =================================================================
         */
        char c1 = 'a';
        char c2 = '中';
        char c3 = '\u0062';

        System.out.println("========================================");
        System.out.println(c1);
        System.out.println((int)c1);
        System.out.println(c2);
        System.out.println((int)c2);
        System.out.println(c3);
        //所有的字符本质还是数字
        //编码 Unicode   2字节

        //转义字符
        // \t     制表符
        // \n     换行

        System.out.println("========================================");
        System.out.println("Hello\tWorld");
        System.out.println("Hello\nWorld");

        //
        System.out.println("========================================");
        String sa = new String("hello world");
        String sb = new String("hello world");
        System.out.println(sa==sb); //相当于比较内存地址段

        String sc = "hello world";
        String sd = "hello world";
        System.out.println(sc==sd);

    }
}

类型转换

  • 由于java是强类型语言,所以要进行有些运算的时候,需要用到类型转换

    (低)byte,short,char ->int -> long -> float ->double(高)

  • 运算中,不同类型的数据先转化为同一类型,然后进行运算。

  • 强制类型转换

  • 自动类型转换

public class demo3 {
    public static void main(String[] args) {
        int i = 128;
        byte b = (byte) i; //内存溢出
        //强制转换  (类型)变量名    高--低

        System.out.println(i);
        System.out.println(b);

        //自动转换   低--高
        double c = i;
        System.out.println(c);

        /*
        注意点
        1. 不能对布尔值进行转换
        2. 不能把对象类型转换为不相干的类型
        3. 在把高容量转换到低容量的时候,强制转换
        4. 转换的时候可能存在内存溢出,或者精度问题
         */

        System.out.println("==================");
        System.out.println((int)23.7); //23
        System.out.println((int)-45.89f); //-45

        System.out.println("==================");
        char c1 = 'a';
        int d = c1 + 1 ;
        System.out.println(d);
        System.out.println((char)d);

    }
}

问题

public class demo04 {
    public static void main(String[] args) {
        //操作比较大的数的时候,注意溢出问题
        //JDK7新特性,数字之间可以用下划线分割
        int money = 1_000_000_000;
        int years = 20;
        int total = money*years; //-1474836480  计算的时候溢出了
        long total2 = money*years; //默认是int;转换之前已经存在问题
        long total3 = money*((long)years);//20_000_000_000
        System.out.println(total);
        System.out.println(total2);
        System.out.println(total3);
    }
}

变量

  • 变量是什么:就是可以变化的量!
  • java是一种强类型语言,每个变量都必须声明期类型
  • java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域
  • 注意事项:
    • 每个变量都有类型,类型可以是基本类型,也可以是引用类型
    • 变量名必须是合法的标识符
    • 变量声明是一条完整的语句,因此每一个声明都必须以分号结束
public class demo05 {
    public static void main(String[] args) {
        int a=1,b=2,c=3;
        String name = "goldtree";
        char x = 'X';
        double pi = 3.1415;
    }
}

变量作用域

  • 类变量
  • 实例变量
  • 局部变量
public class demo05 {
    //类变量 static
    static double salary = 2500;
    //属性:变量
    //实例变量:从属于对象;如果不自行初始化,就自动设置为类型的默认值
    String name;
    int age;
    //main方法
    public static void main(String[] args) {
        //局部变量;必须声明和初始化值
        int i = 10;
        System.out.println(i);

        //变量类型  变量名字 = new demo05();
        demo05 demo05 = new demo05();
        System.out.println(demo05.age); //0
        System.out.println(demo05.name);//null

        //类变量
        System.out.println(salary);

    }
    //其他方法
    public void add(){
        //System.out.println(i);

    }
}

常量

  • 常量:初始化后不能再改变值!不会变动的值
  • 所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变
  • 常量名一般使用大写字符
public class demo06 {

    //修饰符,不存在先后顺序
    static final double PI = 3.14;
    public static void main(String[] args) {
        System.out.println(PI);

    }
}

变量的命名规范

  • 所有变量,方法,类名:见名知意
  • 类成员变量:首字母小写和驼峰原则:mouthSalary
  • 局部变量:首字母小写和驼峰原则
  • 常量:大写字母和下划线:MAX_VALUE
  • 类名:首字母大写和驼峰原则:Man,GoodMan
  • 方法名:首字母小写和驼峰原则:run(),runRun()

运算符

java语言支持的运算符

  • 算数运算符:+ - * / % ++ --
  • 赋值运算符: =
  • 关系运算符:> < >= <= == != instanceof
  • 逻辑运算符:&& || !
  • 位运算符:& | ^ - >> << >>>
  • 条件运算符: ? :
  • 扩展赋值运算符:+= -= *= /=

举例

public class Demo04 {
    public static void main(String[] args) {
        //++ --  自增 自减  一元运算符
        int a = 3;
        int b = a++;
        int c = ++a;
        System.out.println(a); //5
        System.out.println(b); //3
        System.out.println(c); //5
    }
}
package operator;

public class Demo02 {
    public static void main(String[] args) {
        //与 或 非
        boolean a = true;
        boolean b = false;

        System.out.println("a && b: "+ (a && b));
        System.out.println("a || b: "+ (a || b));
        System.out.println("!b: "+(!b));
        
        //短路运算
        int c = 5;
        boolean d = (c<4)&&(c++<4);
        System.out.println(d);
        System.out.println(c);
    }
}
package operator;

public class Demo03 {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;

        a+=b; //a = a+b
        System.out.println(a);

        //字符串连接符 + ,加号边上有string类型,就都变成string
        System.out.println(a+b);
        System.out.println(""+a+b);
        System.out.println(a+b+"");
    }
} 

三元运算符

package operator;

//三元运算符
public class Demo05 {
    public static void main(String[] args) {
        //x ? y : z
        //如果x是true,结果为y,否则结果为z

        int score = 80;
        String type = score <60 ? "不及格":"及格";
        System.out.println(type);
    }
}

包机制

  • 为了更好地组织类,java提供了包机制,用于区别类名的命名空间

  • 包语句的语法格式为:

    package pkg1[. pkg2[. pkg3...]];

  • 一般利用公司域名倒置作为包名

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

    import package1[.package2...].(classname|*);

JavaDoc

  • javadoc命令是用来生成自己API文档的
  • 参数信息
    • @author 作者名
    • @version 版本号
    • @since 指明需要最早使用的jdk版本
    • @param 参数名
    • @return 返回值情况
    • @throws 异常抛出情况
package operator;

/**
 * @author goldtree
 * @version 1.0
 * @since 1.8
 */

public class Doc {
    String name;

    /**
     * 
     * @param name
     * @return
     * @throws Exception
     */
    
    public String test(String name) throws Exception{
        return name;
    }
}

D:\3_doc\java\code\JavaSE\Java_Basic_Syntax\src\main\java\operator>javadoc -encoding UTF-8 -charset UTF-8 Doc.java
正在加载源文件Doc.java...
正在构造 Javadoc 信息...
标准 Doclet 版本 1.8.0_202
正在构建所有程序包和类的树...
正在生成.\operator\Doc.html...
Doc.java:14: 警告: @param 没有说明
     * @param name
       ^
Doc.java:15: 警告: @return 没有说明
     * @return
       ^
Doc.java:16: 警告: @throws 没有说明
     * @throws Exception
       ^
正在生成.\operator\package-frame.html...
正在生成.\operator\package-summary.html...
正在生成.\operator\package-tree.html...
正在生成.\constant-values.html...
正在构建所有程序包和类的索引...
正在生成.\overview-tree.html...
正在生成.\index-all.html...
正在生成.\deprecated-list.html...
正在构建所有类的索引...
正在生成.\allclasses-frame.html...
正在生成.\allclasses-noframe.html...
正在生成.\index.html...
正在生成.\help-doc.html...
3 个警告

Java流程控制

用户交互Scanner对象

  • java提供一个工具,可以获取用户的输入。java.util.Scanner是java5的新特性

  • 基本语法:

    Scanner s = new Scanner(System.in);

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

package control;

import java.util.Scanner;

public class Demo_scanner {
    public static void main(String[] args) {
        //创建一个扫描器对象,用于接受键盘数据
        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入内容: ");
        //判断用户有没有输入字符串
        if(scanner.hasNextLine()){
            //使用next方式接收数据
            //String str = scanner.next();
            String str = scanner.nextLine();
            System.out.println("输入的内容是: "+str);
        }
        else{
            System.out.println("没有输入内容");
        }
        //凡是属于IO流的类,用完就关,要不占用资源
        scanner.close();
    }
}

  • next():
    1. 一定要读取到有效的字符后才可以结束输入
    2. 对输入有效字符之前遇到的空白,next()会自动将其去掉
    3. 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
    4. next()不能得到带有空格的字符串
  • nextLine():
    1. 以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符
    2. 可以获得空白

Scanner进阶使用

package control;

import java.util.Scanner;

public class Demo_scanner_pro {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        //从键盘接收数据
        int i = 0;
        float f = 0.0F;

        System.out.println("请输入整数: ");

        if(scanner.hasNextInt()){
            i = scanner.nextInt();
            System.out.println("整数数据: " + i);
        }else {
            System.out.println("输入的不是整数数据。。。。");
        }


        System.out.println("请输入小数: ");

        if(scanner.hasNextFloat()){
            f = scanner.nextFloat();
            System.out.println("小数数据: " + f);
        }else {
            System.out.println("输入的不是整数数据。。。。");
        }
        scanner.close();

    }


}

举例

package control;

import java.util.Scanner;

public class Demo_scanner_Exp {
    public static void main(String[] args) {
        //我们可以输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束并输出执行结果
        Scanner scanner = new Scanner(System.in);
        //和
        double sum = 0;
        //个数
        int num = 0;

        while(scanner.hasNextDouble()){
            double d = scanner.nextDouble();
            sum = sum + d;
            num = ++num;
        }
        System.out.println(num + "个数的和是: "+ sum);
        System.out.println(num + "个数的平均值是: "+ sum/num);

        scanner.close();

    }
}

顺序结构

  • JAVA的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行
  • 顺序结构是最简单的算法结构
  • 语句与语句之间,框与框之间是按照从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的

IF 选择结构

  • if单选结构
  • if双选结构
  • if多选结构
  • 嵌套的if结构
  • switch多选择结构

if单选结构

package control;

import java.util.Scanner;

public class Demo_if {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.nextLine();
        if(s.equals("hello")){
            System.out.println(s);
        }
        System.out.println("not hello");
        scanner.close();
    }
}

if双选择结构

package control;

import java.util.Scanner;

public class Demo_if_else {
    public static void main(String[] args) {
        //考试分数大于60,显示及格,否则显示不及格
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入考试成绩: ");
        double score = scanner.nextDouble();
        if(score>=60){
            System.out.println("恭喜你,及格了");
        }else {
            System.out.println("不及格");
        }
        scanner.close();
    }
}

if多选结构

package control;

import java.util.Scanner;

public class Demo_if_elseif {
    public static void main(String[] args) {
        //if的多选择结构
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入考试分数: ");
        int score = scanner.nextInt();
        if(score >= 90 && score <= 100){
            System.out.println("A");
        } else if (score >= 80 && score < 90) {
            System.out.println("B");
        } else if (score >= 70 && score < 80) {
            System.out.println("C");
        } else if (score >= 60 && score < 70) {
            System.out.println("D");
        } else if (score < 60 ){
            System.out.println("不及格");
        }else
            System.out.println("分数异常");
        scanner.close();
    }
}

if的嵌套结构

if(){
    if(){
        
    }
}

switch多选择结构

  • 多选择结构还有一个实现方式就是switch case语句
  • switch case 语句判断是一个变量与一些列值中某个值是否相等,每个值称为一个分支
  • switch语句中的变量类型可以是
    • byte short int 或者 char
    • 从java SE 7 开始
    • switch支持字符串String类型
    • 同时case标签必须为字符串常量或
package control;

import java.util.Scanner;

public class Demo_switch {
    public static void main(String[] args) {
        System.out.println("请输入你买的东西名称: ");
        Scanner scanner = new Scanner(System.in);
        String wares = scanner.nextLine();
        switch (wares){
            case "apple":
                System.out.println("你买了" + wares);
                break;
            case "perl":
                System.out.println("你买了" + wares);
                break;
            case "orange":
                System.out.println("你买了" + wares);
                break;
            default:
                System.out.println("你买了别的");

            }
        scanner.close();
        }
    }

循环控制

  • while循环
  • do...while 循环
  • for 循环
  • java5中引入了一种主要用于数组的增强型for循环

while循环

  • while是最基本的循环
  • 只要布尔表达式为true,循环就会一直执行下去
  • 我们大多数情况是会让循环停止下来,我们需要一个让表达式失效的方式让循环停下来
  • 少部分情况需要循环一直执行,比如服务器的请求响应监听等
  • 循环条件一直为true就会造成无限循环
package control;

public class Demo_While {
    public static void main(String[] args) {
        int i = 0;
        int sum = 0;
        while (i < 100){
            i++;
            sum = sum + i;

        }
        System.out.println(sum);
    }
}

do...while循环

  • 对于while语句而言,如果不满足条件,则不能进入循环。但是有时候我们需要即使不满足条件,也至少执行一次。
  • do...while循环和while循环相似,不同的是,do...while循环至少会执行一次
  • while和do...while的区别:
    • while先判断后执行。do...while是先执行后判断
    • do...while总是保证循环体会被至少执行一次。
package control;

public class Demo_Dowhile {
    public static void main(String[] args) {
        int i = 0;
        int sum = 0;

        do{
            i++;
            sum = sum + i;
        }while (i < 100);
        System.out.println(sum);
    }
}

while和dowhile区别

package control;

public class Demo_DiffWhileDowhile {
    public static void main(String[] args) {
        int i = 0;
        while(i < 0 ){
            System.out.println(i);
        }
        System.out.println("=====================");
        do{
            System.out.println(i);
        }while (i < 0);
    }
}

For循环

  • 虽然所有循环结构都可以用while或者do...while表示,但java提供了另一种语句。for循环,使一些循环结构变得更简单。
  • for循环语句是支持迭代的一种通用结构,是最有效,最灵活的循环结构
  • for循环执行的次数是在执行前就确定的

练习1

package control;

public class Demo_For_1 {
    public static void main(String[] args) {
        //0-100内奇数和以及偶数和
        int oddsum = 0;
        int evensum = 0;
        for (int i = 0; i <= 100; i++) {
            if (i%2 != 0){
                oddsum = oddsum + i;
            }else {
                evensum = evensum + i;
            }
        }
        System.out.println("oddsum: "+oddsum);
        System.out.println("evensum: "+evensum);
    }
}

练习2

package control;

public class Demo_For_2 {
    public static void main(String[] args) {
        //输出0-1000中能被5整除的数,每行输出三个

        for (int i = 0; i <= 1000; i++) {
            if(i%5 == 0){
                System.out.print(i+"\t");
            }
            if(i%(5*3) == 0){
                System.out.println();
                //System.out.print("\n");
            }
        }
    }
}

练习3

package control;

public class Demo_For_99 {
    public static void main(String[] args) {
        //打印99乘法表
        for (int i = 1; i < 10; i++) {
            for (int j = 1; j < 10; j++) {
                if (j < 9 ){
                    System.out.print(i*j + "\t");
                }
                if (j == 9 ){
                    System.out.println(i*j + "\t");
                }
            }
        }
    }
}

or
    
package control;

public class Demo_For_99 {
    public static void main(String[] args) {
        //打印99乘法表
        for (int i = 1; i < 10; i++) {
            for (int j = 1; j <= i; j++) {
                if (j < i ){
                    System.out.print(i*j + "\t");
                }
                if (j == i ){
                    System.out.println(i*j + "\t");
                }
            }
        }
    }
}

or

package control;

public class Demo_For_99 {
    public static void main(String[] args) {
        //打印99乘法表
        for (int i = 1; i < 10; i++) {
            for (int j = 1; j <= i; j++) {
               System.out.print(i*j + "\t");
            }
               System.out.println();
            }
        }
    }

增强for循环

package control;

public class Demo_for_enhence {
    public static void main(String[] args) {
        int[] number = {10,20,30,40,50};
        for(int x:number){
            System.out.print(x+"\t");
        }
    }
}

break continue

  • break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。
  • continue语句用在循环语句体中,用于终止某次循环过程,即跳出本次循环。

流程控制练习

package control;

public class Demo_triangle {
    public static void main(String[] args) {
        //打印一个三角形
        for (int i = 1; i <= 5; i++) {
            for (int j = 5; 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方法详解

什么是方法

  • java方法是语句的集合,它们在一起执行一个功能
    • 方法是解决一类问题的步骤的有序组合
    • 方法包含于类或对象中
    • 方法在程序中被创建,在其他地方被引用
  • 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成1个功能,这样有利于后期的扩展
  • 方法的命名规则

练习

package method;

public class Demo01 {
    //main方法
    public static void main(String[] args) {
        int sum = add(1, 2);
        System.out.println(sum);
        System.out.println("===================");
        _99();
    }
    //加法
    public static int add(int a,int b){
        return a+b;
    }
    public static void _99(){
        for (int i = 1; i < 10; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.print(i*j + "\t");
            }
            System.out.println();
        }
    }
}


好耶⎛⎝≥⏝⏝≤⎛⎝好耶

方法的定义

  • java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含一下语法:
  • 方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
    • 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型
    • 返回值类型:方法可能有返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。这种情况下,returnValueType是关键字void。
    • 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
    • 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表时指方法的参数类型,顺序和参数的个数。参数是可选的,方法可以不包含任何参数
      • 形式参数:在方法被调用时用于接收外界输入的数据
      • 实参:调用方法时实际传递给方法的数据
    • 方法体:方法体包含具体的语句,定义该方法的功能。

练习

package method;

public class Demo02 {
    public static void main(String[] args) {
        int max = maxMin(6,6);
        System.out.println(max);

    }

    //    比大小
    public static int maxMin(int num1, int num2) {
        int result = 0;
        if (num1 == num2) {
            System.out.println("num1 == num2");
            return 0; //终止方法
        }

        result = num1 > num2 ? num1 : num2;
        return result;

    }
}


方法调用

  • 调用方法:对象名.方法名(实参列表)

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

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

    int larger = max(30,40);

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

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

  • 扩展了解:值传递(java) 和 引用传递

方法的重载

  • 重载就是在一个类中,有相同的函数名称,但形参不同的函数。
  • 方法的重载的规则:
    • 方法名称必须相同
    • 参数列表必须不同(个数不同,类型不同,参数排列顺序不同等)
    • 方法的返回类型可以相同和可以不同
    • 仅仅返回类型不同不足以称为方法的重载
  • 实现理论:
    • 方法名称相同时,编译器会根据调用方法的参数个数,参数类型等去诸葛匹配,已选择对应的方法,如果匹配失败,则编译器报错。

练习

package method;

public class Demo03 {
    public static void main(String[] args) {
        double max = maxMin(6,7);
        System.out.println(max);

    }
    public static int maxMin(int num1, int num2) {
        int result = 0;
        if (num1 == num2) {
            System.out.println("num1 == num2");
            return 0; //终止方法
        }

        result = num1 > num2 ? num1 : num2;
        return result;

    }
    public static double maxMin(double num1, double num2) {
        double result = 0;
        if (num1 == num2) {
            System.out.println("num1 == num2");
            return 0; //终止方法
        }

        result = num1 > num2 ? num1 : num2;
        return result;

    }
}

命令行传参

  • 有时候希望运行一个程序时候再传递给他消息。这要靠传递命令行参数给main()函数实现。
package method;

public class Demo04 {
    public static void main(String[] args) {
        for (int i = 0; i < args.length; i++) {
            System.out.println("args[" + i + "]: " + args[i]);
        }
    }
}
D:\3_doc\java\code\JavaSE\Java_Basic_Syntax\src\main\java>java method.Demo04 has many args
args[0]: has
args[1]: many
args[2]: args

可变参数

  • JDK1.5开始,java支持传递同类型的可变参数给一个方法
  • 在方法声明中,在指定参数类型后加一个省略号(...)
  • 一个方法中只能指定一个可变参数,它必须时方法的最后一个参数。任何普通的参数必须在它之前声明。
package method;

public class Demo05 {
    public static void main(String[] args) {
        Demo05 demo05 = new Demo05();
        demo05.test(1,2,3);
    }
    public void test(int... i){
        for (int j = 0; j < i.length; j++) {
            System.out.println(i[j]);
        }

    }
}

package method;

public class Demo05 {
    public static void main(String[] args) {
        Demo05 demo05 = new Demo05();
        demo05.test(1,2,3,4,5,6,7);
    }
    public void test(int... number){
//        求最大值
        if(number.length == 0){
            System.out.println("No argument passwd");
            return;
        }
        int result = number[0];
        for (int j = 1; j < number.length; j++) {
            if(number[j] > result){
                result = number[j];
            }
        }
        System.out.println("the max num is :" + result);
    }
}

递归

  • A方法调用B方法,我们很容易理解!
  • 递归就是:A方法调用A方法!就是自己调用自己
  • 利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可描述出解题过程所需要的多次重复计算,大大的减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
  • 递归结构包括两个部分:
    • 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环
    • 递归体:什么时候需要调用自身方法。

举例

package method;

import java.util.Scanner;

public class Demo_recursion {
//    n!
    public static void main(String[] args) {
        int factorial = 0;
        int n = 0;
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入一个整数:");
        n = scanner.nextInt();
        factorial = factorial(n);
        System.out.println(n + "的阶乘结果是:" + factorial);
    }
    public  static int factorial(int n){
        if(n == 1 || n == 0){
            return 1;

        }else{
            return n*factorial(n-1);
        }
    }
}

数组

数组的定义

  • 数组是相同类型数据的有序集合
  • 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
  • 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下表来访问他们

数组声明创建

  • 首先必须声明数组变量,才能在程序中使用数组。

    dataType[] arrayRefVar; //首选方法

    dataType arrayRefVar[]; //效果相同,但是不是首选方法

  • Java语言使用new操作符来创建数组

    dataTpye[] arrayRefVar = new dataType[arraySize];

  • 数组的元素是通过缩影访问的,数组的索引是从0开始的

  • 获取数组的长度:

    arrays.length

举例

package arrays;

public class Demo01 {
    //变量的类型  变量的名字
    //数组类型
    public static void main(String[] args) {
        int[] nums; //定义 1 Java风格

        //int nums2[];//定义 2 C C++风格的

        nums = new int[10]; //这里面可以存放10个int类型的数字

        //给数组元素赋值
        for (int i = 0; i < nums.length; i++) {
            nums[i] = i;
            System.out.println("nums["+ i + "]个元素的值是: " +nums[i]);
        }
    }
}

数组三种初始化

  • 静态初始化

    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;

  • 数组的默认初始化

    • 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化

举例

package arrays;

public class Demo02 {
    public static void main(String[] args) {
        //静态初始化: 创建数组+赋值
        int[] a = {1,2,3,4,5,6,7,8,9};
        System.out.println(a[0]);

        //动态初始化:包含默认初始化
        int[] b = new int[10];
        b[0] = 10;
        System.out.println(b[0]);
        System.out.println(b[1]);
    }
}

数组的四个基本特点

  • 其长度是确定,数组一旦被创建,他的大小就是不可以改变的
  • 器元素必须是相同类型,不允许出现混合类型
  • 数组中的元素可以是任何数据类型,包括基本类型和引用类型
  • 数据变量属于引用类型,数组也可以堪称是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。

数组的边界

  • 下标的合法区间:[0,length-1],如果越界就会报错
  • ArrayIndexOutOfBoundsException:数组下标越界异常
  • 小结
    • 数组是相同数据类型的有序集合
    • 数组也是对象。数组元素相当于对象的成员变量
    • 数组的长度是确定的,不可改变。如果越界,就报错

数组的使用

  • 普通的For循环
  • For-Each循环
  • 数组作方法入参
  • 数组作返回值

普通的For循环

package arrays;

public class Demo03 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5};
        //打印全部元素
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        System.out.println("===============");
        //计算元素的和
        int sum = 0 ;
        for (int i = 0; i < arr.length; i++) {
            sum = sum + arr[i];
        }
        System.out.println("sum:" + sum);
        System.out.println("================");
        //打印最大元素
        int max = 0;
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] > max){
                max = arr[i];
            }
        }
        System.out.println("Max: " +max );
    }
}

For-Each**循环 **

package arrays;

public class Demo04 {
    public static void main(String[] args) {
        int[] arrays = {1,2,3,4,5};

        //JDK1.5,没有下标
        for (int array : arrays) {
            System.out.println(array);
        }
    }
}//类似 for i in 语法

数组作为方法的参数

package arrays;

public class Demo05 {
    public static void main(String[] args) {
        int[] array = new int[5];
        for (int i = 0; i < array.length; i++) {
            array[i] = i;
        }

        printArray(array);
    }
    //打印数组元素
    public static void printArray(int[] arrays){
        for (int i = 0; i < arrays.length; i++) {
            System.out.println(arrays[i]);
        }
    } 

}

数组作为方法的返回值

package arrays;

public class Demo06 {
    public static void main(String[] args) {
        int[] array = new int[5];
        for (int i = 0; i < array.length; i++) {
            array[i] = i;
        }
        int[] array_re = reverse(array);
        printArray(array_re);
    }
    //打印数组
    public static void printArray(int[] arrays){
        for (int i = 0; i < arrays.length; i++) {
            System.out.println(arrays[i]);
        }
    }

    //反转数组
    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;
    }
}

多维数组

  • 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其中每个元素都是一个一维数组。

  • 二维数组

    int a[][] = new int[2][5]; //一个2行5列的数组
    

举例

package arrays;

public class Demo07 {
    public static void main(String[] args) {
        int[][] array = {{1,2,3,4,5},{6,7,8,9,10}};
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[i].length; j++) {
                System.out.print(array[i][j] + " ");
            }
            System.out.println();
        }
    }
}

Arrays类

  • 数组的工具类java.util.Arrays
  • 由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作
  • Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而不用使用对象来调用
  • 具有以下常用功能:
    • 给数组赋值:通过fill方法
    • 对数组排序:通过sort方法,按升序
    • 比较数组:通过equals方法比较数组中元素值是否相等
    • 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作

举例

package arrays;

import java.util.Arrays;

public class Demo08 {
    public static void main(String[] args) {
        int[] a = {1,5,32,8,5,9,3,5,9,2,10,44};
        System.out.println(a);
        //打印数组元素
        System.out.println(Arrays.toString(a));

        //数组排序
        Arrays.sort(a);
        System.out.println(Arrays.toString(a));

        //填充数组
        Arrays.fill(a,2,4,100);
        System.out.println(Arrays.toString(a));
        
        Arrays.fill(a,100);
        System.out.println(Arrays.toString(a));

    }
}

冒泡排序

  • 冒泡排序无疑是最为出名的排序算法之一,总共有八大排序
  • 冒泡的代码还是相当简单的,两层循环,外层冒泡论述,内层依次比较
package arrays;

public class DemoBlow {
    public static void main(String[] args) {
        int[] arr = {1,5,3,7,5,88,55,33,44,67,109,11,21,31,15};
        Blowsort(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

    /*冒泡排序
    1. 比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们位置
    2. 每一次比较,都会产生出一个最大,或者最小的数字
    3. 下一轮则可以少依次排序
    4. 依次循环,直到结束
    */
    public static int[] Blowsort(int[] array) {
        //临时变量
        int temp = 0;
        //外层循环,判断我们这个要走多少次
        for (int i = 0; i < array.length-1; i++) {
            //内层循环,比较判断两个数,如果第一个数比第二个数大,则交换位置
            for (int j = 0; j < array.length-1; j++) {
                if (array[j + 1] < array[j]) {
                    temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }

            }


        }
        return array;
    }
}


稀疏数组介绍

  • 当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组
  • 稀疏数组的处理方式是:
    • 记录数组一共有几行几列,有多少个不同值
    • 把具有不同值得元素和行列及值记录在一个小规模得数组中,从而缩小程序得规模

练习

  • 需求:编写五子棋游戏中,有存盘推出和继续上盘的功能

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

  • 解决:稀疏数组

package arrays;

import java.util.concurrent.LinkedTransferQueue;

public class DemoSparesArray {
    public static void main(String[] args) {
        //1.创建一个二维数组11*11  0:没有棋子,1:黑棋  2:白棋
        int[][] array = new int[11][11];
        array[1][2] = 1;
        array[2][3] = 2;
        //输出原始得数组
        System.out.println("输出原始得数组:");
        for (int[] ints : array) {
            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(array[i][j]!=0){
                    sum++;
                }
            }

        }
        System.out.println("有效值的个数是:"+sum);

        //2. 创建一个稀疏数组
        int[][] sparesarray = new int[sum+1][3];
        sparesarray[0][0] = 11;
        sparesarray[0][1] = 11;
        sparesarray[0][2] = sum;

        //遍历二维数组,将非零的值,存放在稀疏数组中
        int count = 0;
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[i].length; j++) {
                if (array[i][j] != 0) {
                    count++;
                    sparesarray[count][0] = i;
                    sparesarray[count][1] = j;
                    sparesarray[count][2] = array[i][j];
                }

            }
        }
        //输出稀疏数组
        System.out.println("输出稀疏数组:");
        for (int i = 0; i < sparesarray.length; i++) {
            System.out.println(sparesarray[i][0]+"\t"+
                    sparesarray[i][1]+"\t"+
                    sparesarray[i][2]);
        }
        System.out.println("=============");
        System.out.println("还原");
        //1. 读取稀疏数组的值
        int[][] array3= new int[sparesarray[0][0]][sparesarray[0][1]];
        //2. 给其中还原值
        for (int i = 1; i < sparesarray.length; i++) {
            array3[sparesarray[i][0]][sparesarray[i][1]] = sparesarray[i][2];
        }
        //3. 打印
        System.out.println("输出还原的数组:");
        for (int[] ints : array3) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }

    }
}

面向对象编程

面向过程 & 面向对象

  • 面向过程思想
    • 步骤清晰简单,第一步做什么,第二部做什么。。。。
    • 面向过程适合处理一些较为简单的问题
  • 面向对象思想
    • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
    • 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
  • 对于描述复杂的事务,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。

什么是面向对象

  • 面向对象编程(Object-Oriented Programming,OOP)
  • 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
  • 抽象
  • 三大特性:
    • 封装
    • 继承
    • 多态
  • 从认识论角度考虑是先有对象后有类。对象,是具体的事务。类,是抽象的,是对对象的抽象
  • 从代码运行角度考虑是先有类后有对象,类是对象的模板。

类与对象的关系

  • 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物
    • 动物 植物 手机 电脑。。。
    • Person类,Pet类,Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为
  • 对象是抽象概念的具体实例
    • 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例
    • 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念

创建于初始化对象

  • 使用new关键字创建对象
  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
    • 1,必须和类的名字相同
    • 2,必须没有返回类型,也不能写void

练习

创建一个类

package OOP;

//学生类
public class Student {
    //属性:字段
    String name;
    int age;

    //方法
    public void study(){
        System.out.println(this.name + "在学习");
    }

}

创建一个main类

package OOP;

import javax.xml.stream.events.StartDocument;

//一个项目应该只存在一个main方法
public class Application {
    public static void main(String[] args) {
        //类:抽象的,实例化
        //类实例化后会返回一个自己的对象!
        //student对象就是一个Student类的具体实例!
        Student SpongeBob = new Student();
        Student PatrickStar = new Student();

        SpongeBob.name = "海绵宝宝";
        PatrickStar.name = "派大星";
        SpongeBob.age = 3;
        PatrickStar.age = 3;

        System.out.println(SpongeBob.name);
        System.out.println(SpongeBob.age);
        System.out.println(PatrickStar.name);
        System.out.println(PatrickStar.age);
    }
}

构造方法

测试类

package OOP;

public class Person {
    //一个类即使什么都不写,它也会存在一个方法
    //显示的定义构造器
    //无参构造器
    String name;

    //实例初始化值
    //1. 使用new关键字,必须要有构造器
    public Person(){
        this.name = "SpongeBob";
    }

    //有参构造: 一旦定义了有参构造,无参构造就要显示定义

    public Person(String name) {
        this.name = name;
    }
}

//alt + insert 可以自动生成构造器

测试主类

package OOP;

import javax.xml.stream.events.StartDocument;

//一个项目应该只存在一个main方法
public class Application {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person.name);

        Person person1 = new Person("PartrickStar");
        System.out.println(person1.name);
    }
}

封装

  • 该露的露,该藏的藏
    • 我们程序设计要求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅仅暴露少量的方法给外部使用
  • 封装(数据的隐藏)
    • 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
  • 记住这句话就够了:属性私有,get/set

举例

Student类

package OOP.Demo04;

public class Student01 {

    //属性私有
    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;
    }
//alt insert
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if(age < 20 && age > 0){
            this.age = age;
        }else {
            this.age = 1;
        }
    /*
    * 1. 提高程序的安全性,保护数据
    * 2. 隐藏代码的实现细节
    * 3. 同一接口
    * 4. 系统可维护增加了*/
    }
}

main类

package OOP;

import OOP.Demo04.Student01;

import javax.xml.stream.events.StartDocument;

//一个项目应该只存在一个main方法
public class Application {
    public static void main(String[] args) {
        Student01 s1 = new Student01();
        Student01 s2 = new Student01();

        s1.setName("SpongeBob");
        System.out.println(s1.getName());

        s1.setAge(100);
        System.out.println(s1.getAge());

    }
}

继承

  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
  • extends的意思是“扩展”。子类是父类的扩展
  • JAVA中类只有单继承,没有多继承!
  • 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖,组合,聚合等。
  • 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示
  • 子类和父类之间,从意思上讲应该具有“is a”的关系
  • object类
  • super
  • 方法重写

举例

package OOP.Demo05;

//基类
public class Person {
    //public
    //protected
    //default
    //private
    private int money = 100_000_000;

    public void say(){
        System.out.println("我是人");
    }

    public int getMoney() {
        return money;
    }

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

//派生类 子类
public class Student extends  Person{
    //ctrl + h
}
package OOP.Demo05;

//派生类 子类
public class Teacher extends Person{
}
package OOP;

import OOP.Demo05.Student;

import javax.xml.stream.events.StartDocument;

//一个项目应该只存在一个main方法
public class Application {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.say();
        System.out.println("继承了钱 = " + s1.getMoney());

    }
}

Super详解

package OOP.Demo05;

//基类
public class Person {
    public Person() {
        System.out.println("父类的无参构造器执行了");
    }

    protected String name = "SpongeBob";

    public void print(){
        System.out.println("这是父类中打印的内容");
    }
}
package OOP.Demo05;

//派生类 子类
public class Student extends  Person{
    public Student() {
        System.out.println("student子类的无参构造器执行了");
    }

    //ctrl + h
    private String name = "PartickStar";

    public void test(String name){
        System.out.println(name);
        System.out.println(this.name);
        System.out.println(super.name);

    }

    public void print(){
        System.out.println("这是student子类中打印的内容");
    }
    public void test1 (){
        print();
        this.print();
        super.print();
    }
}
package OOP;

import OOP.Demo05.Student;

import javax.xml.stream.events.StartDocument;

//一个项目应该只存在一个main方法
public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        //student.test("goldtree");
        //student.test1();

    }
}

总结

super注意点:

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

Vs this:

  1. 代表的对象不同:
    • this 本身调用者这个对象
    • super 代表父类对象的引用
  2. 前提
    • this 没有继承也可以使用
    • super 只能在继承条件才可以使用
  3. 构造方法
    • this() 本类的构造
    • super() 父类的构造

方法重写

package OOP.Demo06;

public class B {
    public  void test(){
        System.out.println("B-->test");
    }
}
package OOP.Demo06;

public class A extends B{
    public  void test(){
        System.out.println("A-->test");
    }
}
package OOP;


import OOP.Demo06.A;
import OOP.Demo06.B;

import javax.xml.stream.events.StartDocument;

//一个项目应该只存在一个main方法
public class Application {
    public static void main(String[] args) {
        A a = new A();
        a.test();

        B b = new A();
        b.test();
    }
}

总结

  1. 需要有继承关系,子类重写父类的方法!
  2. 方法名必须相同
  3. 参数列表必须相同
  4. 修饰符:范围可以扩大,不能缩小
  5. 抛出的异常:范围可以被缩小,但不能被扩大
  6. 子类的方法和父类的方法需要一致,方法体不同

为什么需要重写

  1. 父类的功能,子类不一定需要,或者不满足子类需要
  2. alt + insert : overwrite

多态

  • 即同一方法可以根据发送对象的不同而采用不同的行为方式
  • 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
  • 多态存在的条件:
    • 有继承关系
    • 子类重写父类方法
    • 父类引用指向子类对象
  • 注意:多态是方法的多态,属性没有多态性
  • instanceof 类型转换 引用类型转换

举例

package OOP.Demo07;

public class Person {
    public void run(){
        System.out.println("Person---run");
    }
}
package OOP.Demo07;

public class Student extends Person{
    public void run(){
        System.out.println("Student---run");
    }
}
package OOP;


import OOP.Demo07.Person;
import OOP.Demo07.Student;

import javax.xml.stream.events.StartDocument;

//一个项目应该只存在一个main方法
public class Application {
    public static void main(String[] args) {
        //一个对象的实际类型是确定的
        //new Student();
        //new Person();

        //可是指向的引用类型就不确定了,父类的引用指向子类
        //Student 能调用的方法都是自己的或者继承父类的
        Student s1 = new Student();
        //Person父类 可以指向子类,但是不能调用子类独有的方法
        Person s2 = new Student();
        Object s3 = new Student();

        s1.run();
        s2.run();

    }
}
/*
多态注意事项
1. 多态是方法的多态,属性没有多态
2. 父类和子类的关系
3. 
*/

instanceof

package OOP.Demo07;

public class Teacher extends Person{
}
package OOP.Demo07;

public class Student extends Person{

}
package OOP.Demo07;

public class Teacher extends Person{
}
package OOP;


import OOP.Demo07.Person;
import OOP.Demo07.Student;
import OOP.Demo07.Teacher;

import javax.xml.stream.events.StartDocument;

//一个项目应该只存在一个main方法
public class Application {
    public static void main(String[] args) {
        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(student instanceof String);//编译报错
    }
}

static详解

package OOP.Demo08;

//静态导入包
import static java.lang.Math.random;
public class Test {
    {
        System.out.println("匿名代码块");
    }
    static {
        System.out.println("静态代码块");
    }

    public Test() {
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        Test test1 = new Test();
        System.out.println("=================");
        Test test2 = new Test();
        System.out.println("==================");
        System.out.println(random());
    }
}

抽象类

  • abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
  • 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类
  • 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
  • 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
  • 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类

例子

package OOP.Demo09;

//abstract  抽象类  类 extends 单继承 想要多继承 怎么办 接口可以多继承
public abstract class Action {
    //约束 有人帮我们实现
    //抽象方法,只有方法名字,没有方法的实现
    public abstract void doSomething();

    //1. 不能new这个抽象类,只能靠子类去实现它
    //2. 抽象类中可以写普通的方法
    //3. 抽象方法必须在抽象类中
    //抽象的抽象:约束
}

package OOP.Demo09;

//抽象类的所有方法,继承了它的子类,都必须要实现它的方法
public class A extends Action{
    @Override
    public void doSomething() {

    }
}

接口

  • 普通类:只有具体实现
  • 抽象类:具体实现和规范(抽象方法)都有
  • 接口:只有规范!
  • 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是...则必须能...”的思想。如果你是天使,则必须能飞。如果你是好人,则必须干掉坏人。如果你是换人,则必须欺负好人。
  • 接口的本质是契约,就像我们人间的法律一样。指定好后大家都遵守
  • OO的精髓,是对对象的抽象。最能体现这一点的就是接口,为什么我们讨论设计模式都只针对具备了抽象能力的语言(c++ java C等),就是因为设计模式所研究的,实际上就是如何合理的去抽象

举例

package OOP.Demo10;

//interface 定义的关键字,接口都需要有实现类
public interface UserService {

    //常量 public static final
    public static final int age = 99;

    //接口中的所有定义其实都是抽象的 public abstract
    public abstract void addSomething(String name);
    public abstract void delSomething(String name);
    public abstract void updateSomething(String name);
    public abstract void querySomething(String name);
}

package OOP.Demo10;

public interface TimeService {
    void timer();
}

package OOP.Demo10;

//类可以实现接口 implements 接口
//抽象类  extends
//实现了接口的类,就需要重写接口中的方法
//多继承 利用接口实现多继承
public class UserServiceImpl implements UserService,TimeService{
    @Override
    public void addSomething(String name) {

    }

    @Override
    public void delSomething(String name) {

    }

    @Override
    public void updateSomething(String name) {

    }

    @Override
    public void querySomething(String name) {

    }

    @Override
    public void timer() {

    }
}

接口作用

  1. 约束
  2. 定义一些方法,让不同的人实现
  3. public abstract final
  4. 接口本能被实例化,接口中没有构造方法
  5. implements 可以实现多个接口
  6. 实现接口,必须要重写接口中的方法

内部类

  • 内部类就是在一个类的内部再定义一个类,比如,A类中定义一个B类,那么B类相对来说就称为内部类,而A类相对B类来说就是外部类
    1. 成员内部类
    2. 静态内部类
    3. 局部内部类
    4. 匿名内部类

举例

package OOP.Demo11;

public class Outer {
    private int id = 10;
    public void out(){
        System.out.println("这是外部类的方法");
    }

    public class Inner{
        public void in(){
            System.out.println("这是内部类的方法");
        }

        //获得外部类的私有属性
        public void getID(){
            System.out.println(id);
        }
    }

    //局部内部类
    public void method(){
        class Inner{
            public void in(){}
        }
    }
}
package OOP;


import OOP.Demo11.Outer;
import jdk.internal.org.objectweb.asm.tree.InnerClassNode;

//一个项目应该只存在一个main方法
public class Application {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.out();

        //通过外部类实例化内部类
        Outer.Inner inner = outer.new Inner();
        inner.in();
        System.out.println("============");
        inner.getID();
    }
}

异常机制

什么是异常

  • 实际工作中,遇到的情况不可能是非常完美的。比如,你写的某个模块,用户输入不一定符合你的要求,你的程序要打开某个文件,这个文件可能还不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序再运行着,内存或硬盘可能满了,等等。。。
  • 软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,Exception。这些异常,怎么让我们写的程序做出合理的处理。而不至于程序崩溃。
  • 异常指程序运行中出现的不期而至的各种状况,例如:文件找不到,网络连接失败,非法参数等
  • 异常发生在程序运行期间,它影响了正常的程序执行流程。

简单分类

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

  • 检查性异常:最具代表的检查性异常时用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在的文件时,一个异常就发生了,这些异常在编译时不能被简单的忽略。
  • 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
  • 错误:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译时也检查不出来。

ERROR

  • Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
  • Java虚拟机运行错误,当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机一般会选择终止线程;
  • 还有发生在虚拟机试图执行应用时,如类定义错误,链接错误。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的情况。

Exception

  • 在Exception分支中有一个重要的子类RuntimeException

    • ArrayIndexOutOfBoundsException
    • NullPointerException
    • ArithmeticException
    • MissingResourceException
    • ClassNotFoundException

    这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理

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

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

异常处理机制

  • 抛出异常
  • 捕获异常
  • 异常处理五个关键字
    • try catch finally throw throws

举例

package exception;

import OOP.Demo08.Test;

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

        int a = 1;
        int b = 0;
        //选中代码 ctrl + alt + t
        try{ //try监控区域
            System.out.println(a/b);
        }catch (ArithmeticException e){
            System.out.println("除数b不能是0");
        }finally { //处理善后工作 可以不要
            System.out.println("程序结束");
        }
        System.out.println("=================");

        //假设要捕获多个异常,从小到大写
        try{
            new Demo01().a();
        }catch (Error e){
            System.out.println("Error");
        }catch (Exception e){
            System.out.println("Exception");
        }catch (Throwable e){
            System.out.println("Throwable");
        }
        System.out.println("===============");
        try {
            if (b==0){//throw throws
                throw new ArithmeticException();//主动抛出异常
            }
            System.out.println(a/b);
        } catch (Error e) {
            System.out.println("Error");
        }
    }
    public void a(){b();}
    public void b(){a();}

}

自定义异常

  • 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需要继承Exception类即可
  • 在程序中使用自定义异常类,大体可分为以下几个步骤:
    1. 创建自定义异常类
    2. 在方法中通过throw关键字抛出异常对象
    3. 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处,通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
    4. 在出现异常方法的调用者中捕获并处理异常

举例

package exception;

//自定义的异常类
public class MyException extends Exception{
    //传递数字 >10
    private int detaile;

    public MyException(int detaile) {
        //super(message);
        this.detaile = detaile;
    }
    //toString 异常的打印信息

    @Override
    public String toString() {
        return "MyException{" +
                "detaile=" + detaile +
                '}';
    }
}
package exception;

public class Test {
    //可能会存在异常的方法
    static void test(int a) throws MyException{
        if(a>10){
            throw new MyException(a); //抛出异常
        }
        System.out.println("OK");
    }

    public static void main(String[] args) {
        try {
            test(100);
        } catch (MyException e) {
            System.out.println("MyException=>"+e);
        }
    }
}

实际应用中的经验总结

  • 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
  • 在多重catch块后面,可以加上一个catch(Exception)来处理可能会被遗漏的异常
  • 对于不确定的代码,也可以加上try-catch,处理潜在的异常
  • 尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输出
  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定
  • 尽量添加finally语句块去释放占用的资源
posted @ 2022-12-22 16:30  goldtree358  阅读(21)  评论(0编辑  收藏  举报