JAVA 语言基础学习

JAVA 语言基础

Java概述

Java语言的诞生

​ 1991年,James Gosling在SUN公司的工程师小组想要设计这样一种小型计算机语言。该语言主要用于像电视盒这样的消费类电子产品。另外,由于不同的厂商选择不同的CPU和操作系统,因此,要求该语言不能和特定的体系结构绑在一起,要求语言本身是中立的,也就是跨平台的。所以,将这个语言命名为“Green”,类似于绿色软件的意思。后来,改名为Oak,橡树的意思。改名后发现已经有一种语言叫这个名字了,再改名叫 Java

JAVA语言的发展

1991年,SUN公司的Green项目,Oak

1995年,推出Java测试版

1996年,JDK1.0

1997年,JDK1.1

1998年,JDK1.2,大大改进了早期版本缺陷,是一个革命性的版本,更名为Java2。

2004年,J2SE 5.0 (1.5.0) Tiger老虎

2006年,J2SE 6.0 (1.6.0) Mustang野马

2011年,JavaSE7.0 Dolphin海豚

2014年,JavaSE8.0

2017年,JavaSE9.0

2018年,JavaSE10.0

JAVASE(Java Platform Standard Edition)标准版。

​ 是为开发普通桌面和商务应用程序提供的解决方案

JAVAME(Java Platform To Micro Edition)小型版

​ 是为开发电子消费产品和嵌入式设备提供的解决方案

JAVAEE(Java Platform To Enterprise Edition)企业版

​ 是为开发企业环境下的应用程序提供的一套解决方案

JAVA语言的特点

​ 跨平台 —— compile once,run anywhere

​ 面向对象 解释型

​ 健壮 动态

​ 分布式 高效

​ 多线程 结构中立(字节码)

​ 开源

什么是跨平台性?

​ 通过Java语言编写的应用程序在不同的系统 平台上都可以运行。

跨平台的实现原理

Java程序是在Java虚拟机上运行,而非直接运行于操作系统

JDK与JRE

JRE(JAVA Runtime Environment)

​ 包括Java虚拟机,运行时核心类库(rt.jar),JRE主要是给已经写好的Java程序使用,换句话说Java程序要能在操作系统中运行,必须有JRE

JDK(JAVA Develop kit)

​ 首先,JDK包含JRE,除此之外,JDK中还包含一些,供开发者使用的工具比如Javac,Javap等,仅仅只供开发者在开发阶段使用的工具。

JDK的下载和安装

JDK下载

JDK安装

​ 建议JDK安装路径中不要有中文,同时当提示安装JRE时,可以选择不安装

Path和Classpath环境变量

path环境变量

​ 告诉操作系统到哪里去找javac可执行程序配置

classpath环境变量

​ 给jvm用,告诉jvm到哪里加载字节码文件配置

开发工具

​ 开发Java程序,可以使用的工具很多:

  • notepad(微软操作系统自带)
  • Notepad++
  • Eclipse
  • MyEclipse
  • IDEA(Community Ultimate)

关键字

关键字的含义

被Java语言赋予特殊含义的单词

关键字的特点

组成关键字的字母全部小写

关键字的注意事项

高级的编辑器或者专门的开发工具中,关键字会有高亮效果

goto和const作为保留字存在,目前并不使用

标识符

​ 就是给类,接口,方法,变量等起名字时使用的字符序列

组成规则

英文大小写字母

数字字符

$和_

注意事项

英文大小写字母

数字字符

$和_

命名规则

常见命名规则驼峰命名

  • 包命名

    单级 一个全部小写的单词

    多级包名 以域名反转的方式来命名,单词全部小写,单词之间以.分隔

  • 类和接口命名

    单个 首字母大写,其余字母全部小写

    多个单词 每个单词首字母大写,其余字母全部小写

  • 变量和方法的命名

    单个 所有字母小写

    多个单词 第一个单词首字母小写,从第二个单词开始,每个单词首字母大写

  • 常量的命名

    单个 单词的所有字母全部大写即可

    多个单词 每个单词全部大写,单词之间以_来分隔

在实际开发当中,命名要遵循的一个核心原则:见名知意

注释

用于解释说明的文字

Java语言的注释分类:

  • 单行注释

    格式

  • 多行注释

    格式 注释内容

  • 文档注释

    格式 文档注释内容

千万不要忽视注释的作用!!

​ 写代码

​ 项目维护,阅读代码

​ 案例

变量

类 型 占用存储空间 表数范围
byte 1字节 -127~127
short 2字节 2 15 -2^{15} ~ 2 15 1 2^{15}-1
int 4字节 2 31 -2^{31} ~ 2 31 1 2^{31}-1
long 8字节 2 63 -2^{63} ~ 2 63 1 2^{63}-1
float 4字节 -3.403E38 ~ 3.403E38
double 8字节 -1.798E308 ~ 1.798E308

数据类型的转换

  • boolean类型的值不能直接转化为其它数据类型的值

  • 默认(自动)的转化规则

    byte,short,char—>int—>long—>float—>double

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

  • 强制转化

    目标类型 变量名=(目标类型)(被转换的数据);

运算符

算术运算符

运算符 运算 范例 结果
+ 正号 +3 3
- 负号 b=4; - b; -4
+ 5+5 10
- 6-4 2
* 3*4 12
/ 5/5 1
% 取模 5%5 0
++ 自增(前) a=2; b=++a a=3; b=3
++ 自增(后) a=2; b=a++ a=3; b=2
自减(前) a=2; b=–a a=1; b=1
自减(后) a=2; b=a– a=1; b=2
+ 字符串相加 “He”+“llo” “Hello”
"+"三种用法
        //1.加法
        int a =1 ;
        int b = 2;
        System.out.println(a + b);

        //2.表示正数的正号
        a = +1;
        //3.字符串拼接
        //操作数1 + 操作数2  两个操作数中,只要至少有一个是字符串,+操作执行的就是字符串拼接
        System.out.println("hello" + 'a' + 1);
        System.out.println('a' + 1 + "hello");
        System.out.println("5+5=" + 5 + 5);
        System.out.println(5+5+"=5+5");



"/"用法
   /: 除法运算
   %: 求余数的操作
       int a = 3;
       int b = 2;
       //当参与除法运算的除数和被除数,他们都是参数的时候,此时除法运算的结果
       //会丢弃小数部分,只保留整数部分
       int c = a / b;
       System.out.println("c = " + c); 
       
       double d = a / b;
       System.out.println("d = " + d);
       //隐式类型转化
       double e = 1.0 * a / b;
       System.out.println("e = " + e);
"++""--"
   //++
   int a = 1;
   a++;
   System.out.println("a++ = " + a);
   a = 1;
   ++a;
   System.out.println("++a = " + a);

   //--
   int b = 2;
   b--;
   System.out.println("b-- = " + b);
   b = 2;
   --b;
   System.out.println("--b = " + b);

   //++在前和在后的区别
   a = 1;
   int result = a++ + 1;
   //System.out.println(result);
   //System.out.println(a);

   a = 1;
   result = ++a + 1;
   //System.out.println(result);
   //System.out.println(a);

   //--
   b = 2;
   result = b-- - 1;
   System.out.println(result);
   System.out.println(b);

   b = 2;
   result = --b - 1;
   System.out.println(result);
   System.out.println(b);

   //
   a = 4;
   //     4  +  6   +  60
   b = (a++) + (++a) + (a * 10);
   System.out.println(b);

赋值运算符

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

其中 *=====* 为基本的赋值运算符,其他的为扩展的赋值运算符

​ +=, -=, *=, /=, %=: 复合赋值运算

​ a += 3 <-> a 执行相应运算,之后的结果在赋值给a

​ a = a + 3

    int a = 1;

比较运算符

运算符 运算 范例 结果
== 相等于 4==3 false
!= 不等于 4!=3 true
< 小于 4 < 3 false
> 大于 4 > 3 true
<= 小于等于 4 <= 3 false
>= 大于等于 4 >= 3 true
instanceof 检查是否是类的对象 “Hello” instanceof String true

​ 关系运算符的结果只有两种 true or false

    int a = 3;
    int c = 4;
    boolean b = a > c;
    System.out.println(b);

逻辑运算符

&: true & false = false true & true = true false & true = false false & false = false

​ 只要至少有一个操作数是false,结果就是false,只有当两个操作数都是true的时候,&运算的结果,才是true

|: true | false = true true | true = true false & true = true false | false = false

​ 只要至少有一个操作数是true,结果就是true,只有当两个操作数都是false,|运算的结果,才是false

!: !true = false !false = true

注意事项:

单“&”与双“&&”的区别(短路)

&& VS & 都是与运算,他们有什么区别呢?

&& 与运算比较智能, 当它发现&&运算符的第一个操作数结果已经是false,

​ 第二个操组数(对应的表达式)不去管他,直接得到结果&&的结果false

& 这种与运算,比较的死板,即使&第一个操作数,它已经是false,此时它仍然会计算第二个操作数(表达式),在把计算好的两个操作数的结果,做与运算,得到最终结果

&&: 有短路效果,当第一个操作数为false,直接得出与运算的结果

​ 或运算符只要至少有一个操作数是true,结果就是true

==||==或运算比较智能,有短路效果

异或运算 ^ : 相同为false, 不同为true

true ^ true = false false ^ false = false

true ^ false = true false ^ true = true

    int a = 2;
    int b = 3;

    boolean c = a > b & a++ == 0;
    System.out.println(a);
    a = 2;
    //证明&& 操作符比较智能
    c = a > b && a++ == 0;
    System.out.println(a);

    //证明||有短路效果
    a = 2;
    c = a < b || a++ == 0;
    System.out.println(a);


    //异或运算
    c = true ^ false;
    c = true ^ true;
    System.out.println(c);

    //表示一个范围
    a = 3;
    //判断a变量的值是否在[1,10)   1 <= a < 10
    //c = 1 <= a  < 10;
    c = a >= 1 && a < 10;  //判断变量a的值是否在[1,10)

位运算符

位运算符
运算符 运算 范例
<< 左移 3<<2 = 12 -->
>> 右移 3>>1 = 1 -->
>>> 无符号右移 3>>>1 = 1 -->
& 与运算 6&3 =2
| 或运算
^ 异或运算 6^3 = 5
~ 按位取反 ~6 = -7
位运算符的细节
<< 空位补0,被移除的高位丢弃
>> 被移位的二进制最高位是0,右移后,空缺位补0;
最高位是1,最高位补1。
>>> 被移位二进制最高位无论是0或者是1,空缺位都用0补。
& 任何二进制位和0进行&运算,结果是0;
和1进行&运算结果是原值。
| 任何二进制位和0进行 | 运算,结果是原值;
和1进行 | 运算结果是1。
^ 任何相同二进制位进行 ^ 运算,结果是0;
不相同二进制位 ^ 运算结果是1。

小练习

​ 1.请用最有效率的方式写出计算2乘以8的结果 2.请自己实现两个整数变量的交换

​ 2.请自己实现两个整数变量的交换

       //1.
        int a = 2 << 3;
        System.out.println(a);

        //2.请自己实现两个整数变量的交换(才是开发中常用的)
        int a = 10;
        int b = 200;
        //两个变量的交换
        int tmp = a;
        a = b;
        b = tmp;
        System.out.println("a = " + a + "----- b = " + b);

        //变量交换的实现方式2: //ctrl + alt + l
        a = 10;
        b = 200;
        a = a + b;
        b = a - b; // a + b - b = a
        a = a - b; // a + b - a = b
        System.out.println("a = " + a + "----- b = " + b);

        //实现方式3:
        a = 10;
        b = 200;
        a = a ^ b;
        b = a ^ b;// a ^(b ^ b) = a
        a = a ^ b;// a ^ b ^ a -> a ^ a ^ b
        System.out.println("a = " + a + "----- b = " + b);

        //实现方式4
        a = 10;
        b = 200;
        //  (a + b) - a = b
        a = (a+b) - (b=a); //(b = a) 表达式的值是赋值之后的b的值
        System.out.println("a = " + a + "----- b = " + b);

三目运算符

格式

关系表达式 ?表达式1 : 表达式2

如果关系表达式结果为为true,运算后的结果是表达式1;

如果关系表达式结果为false,运算后的结果是表达式2;

public class Demo {

  public static void main(String[] args) {
    int a;
    int b;

    //使用键盘输入
    Scanner sc = new Scanner(System.in);

    a = sc.nextInt();
    b = sc.nextInt();

    //用关系表达式判断两数是否相同
    String s = a == b ? "两数相等" : "两数不相等";
    System.out.println(s);

    // 3数取大
    int c = 100;

    //两数取大,第三个数和两数中的大者比较,取它们的大者就是最大值

    int tmp = a > b ? a : b;
    int result = tmp > c ? tmp : c;
    System.out.println("最大的是: " + result);

    //三目运算的,3数取大的嵌套形式
    //int tmp = a > b ? a : b;
    //int result = tmp > c ? tmp : c;
    result = (a > b ? a : b) > c ? (a > b ? a : b) : c;
    System.out.println("最大的是: " + result);



  }

}

键盘录入数据

用法

    //导包语句(放到class定义的上面):
    import java.util.Scanner;

    //创建对象
    Scanner sc = new Scanner(System.in);

    //从键盘输入读取数据
    int x = sc.nextInt();

练习

键盘录入两个数据,并对这两个数据求和,输出其结果

键盘录入两个数据,获取这两个数据中的最大值

键盘录入三个数据,获取这三个数据中的最大值

键盘录入两个数据,比较这两个数据是否相等

import java.util.Scanner;

public class Demo {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        //键盘录入两个数据,并对这两个数据求和,输出其结果
        System.out.print("请输入a:");
        int a = in.nextInt();
        System.out.print("请输入b:");
        int b = in.nextInt();
        System.out.println("a+b=" + (a + b));

        //键盘录入两个数据,获取这两个数据中的最大值
        System.out.print("请输入c:");
        int c = in.nextInt();
        System.out.print("请输入d:");
        int d = in.nextInt();
        System.out.println(c + "和" + d + "中最大的是:" + Math.max(c, d));

        //键盘录入三个数据,获取这三个数据中的最大值
        System.out.print("请输入e:");
        int e = in.nextInt();
        System.out.print("请输入f:");
        int f = in.nextInt();
        System.out.print("请输入g:");
        int g = in.nextInt();
        System.out.println(e +"、"+f+"和" + g + "中最大的是:" +Math.max(Math.max(e, f), g));

        //键盘录入两个数据,比较这两个数据是否相等
        System.out.print("请输入h:");
        int h = in.nextInt();
        System.out.print("请输入i:");
        int i = in.nextInt();

        String string = (h==i)?"相等":"不相等";
        System.out.println(h + "和" + i + " " + string);
        
        in.close();

    }
}

    

流程控制

一个Java程序,通常是由多条符合Java语法规则的语句组成的。

一个Java程序的执行,一定意味着多条Java语句的执行。

​ 既然是多条Java语句的执行,执行的结果就一定与语句执行的顺序有关,同样的语句,不同的执行顺序,结果可能不同

顺序结构

  • 顺序结构:描述的是Java语句之间,从上到下(或从左到右)依次执行的执行顺序
  • 顺序结构是程序中最简单最基本的流程控制,没有特定的语法,就是按照代码书写的顺序执行。
  • 对于顺序结构而言,写在前面的代码先执行,写在后面的代码后执行
    int i = 1;
    int b = 2;

选择结构

​ 选择结构中的代码顺序和顺序结构中代码的执行顺序有明显的不同:

​ 选择结构有特定的语法规则,代码要执行具体的逻辑运算进行判断。

​ 逻辑运算的结果有两个,所以产生选择,按照不同的选择执行不同的代码。

​ Java中,选择结构有2种实现形式,if语句 和switch语句

if选择结构

  1. 单分支的选择结构: 如果…就

    判断提条件的结果只能是true or false

    if(判断条件) {
      //语句体
    }

​ 判断条件是由一个 关系表达式 来表示的

    Scanner in = new Scanner(System.in);

    int input = in.nextInt();

    //单分支的 if 当用户输入的是正数就输出一下,否则什么都不做
    if (input > 0) {
        System.out.println("亲,您输入的是一个正数:" + input);
    }
  1. 双分支:如果…就。。,否则。。。
    if (判断条件) {

    } else {

    }
    Scanner in = new Scanner(System.in);

    int input = in.nextInt();
    //双分支  当用户输入正数的时候输出一下用户输入的正数,当用户输入了非正数提示一下,请用户输入正数
    if (input > 0) {
        System.out.println("亲,您输入的是一个正数:" + input);
    } else {
        System.out.println("亲,请重新输入一个正数");
    }
  1. 多分支(各个分支,平行,互斥)
    if(判断条件1) {
     条件1语句体
     } else if (条件2) {
     条件2语句体
     }
     ...
     else if (条件n) {

     } else {
       // 第n + 1种情况
      //当else前都不满足条件的时候,就会执行else中的语句体
     }

   Scanner in = new Scanner(System.in);

   int input = in.nextInt();
   //多分支 当用户输入正数,0,负数
   if (input > 0) {
       System.out.println("亲,您输入的是一个正数:" + input);
   } else if (input == 0) {
       System.out.println("亲,您输入了一个0");
   } else {
       System.out.println("亲,请重新输入一个数字");
   }
	在绝大部分场景下,三目运算符和if双分支选择结构,都可以相互替代,
    //关于双分支的if选择结构
    // 实现两数取大
    int a = 3;
    int b = 10;
    int max;
    if (a > b) {
      max = a;
    } else {
      max = b;
    }

    //可以用三目运算符来实现两数取大
    max = a > b ? a : b;

​ 但是,如果选择结构执行的仅仅只是一个操作,没有返回值,此时if双分支选择结构不可以和三目运算相互替代

    //我们发现3目运算符的语义和if双支选择结构,语义几乎完全相同,
    // 都是非此即彼,但是至少有一种情况,它们不能相互替代
    if (a > b) {
      System.out.println("大者是" + a);
    } else {
      System.out.println("大者是" + b);
    }

    //三目运算符的结果一定是一个值
    //a > b ? System.out.println("大者是" + a) : System.out.println("大者是" + b);

小练习

1.键盘录入x的值,计算出y的并输出。

x和y的关系满足如下:

​ x>=3 y = 2x + 1;

-1<=x<3 y = 2x;

​ x<=-1 y = 2x – 1;

    Scanner scanner = new Scanner(System.in);
    int x = scanner.nextInt();
    int y;
    if ( x >= 3) {
      y = 2 * x + 1;
    } else if (x >= -1 && x < 3) {
      y = 2 * x;
    } else {
      // x <= -1
      y = 2 * x - 1;
    }
    System.out.println("x = " + x + "---- y = " + y);

2.键盘录入月份的值,输出对应的季节。

  12   1  2 冬季  

​ 3 4 5 春季

​ 6 7 8 夏季

​ 9 10 11 秋季

    if (x == 12 || x == 1 || x == 2) {
      //冬季
      System.out.println("冬季");
    } else if ( x >= 3 && x <= 5) {
      //春季
      System.out.println("春季");
    } else if ( x >= 6 && x <= 8 ) {
      //夏季
      System.out.println("夏季");
    } else if ( x >= 9 && x <= 11) {
      //秋季
      System.out.println("秋季");
    } else {
      //应对用户错误的输入
      System.out.println("亲,您输入了错误的月份");
    }

3.获取三个数据中的最大值

    int a = 10;
    int b = 20;
    int c = 15;

    //if的嵌套来实现
    //if (a > b) {
    //  // a大
    //  if(a > c) {
    //    // a 最大
    //    System.out.println("最大值是: " + a);
    //  } else {
    //    // c最大
    //    System.out.println("最大值是 " + c);
    //  }
    //} else {
    //  // b大
    //  if (b > c) {
    //    System.out.println("最大值是: " + b);
    //  } else {
    //    System.out.println("最大值是: " + c);
    //  }
    //}

    //非嵌套方式
    int tmp;
    if ( a > b) {
      tmp = a;
    } else {
      tmp = b;
    }

    if (tmp > c) {
      System.out.println(tmp);
    } else {
      System.out.println(c);
    }

Switch选择结构

​ switch语句格式

     switch(表达式) { 
         case1//这个值,代表的一个特定分支 
            语句体1; //满足条件的分支执行的语句体 
            break; 
         case2: 
            语句体2;
            break;default: 
            语句体n+1; 
            break; 
     }

格式解释

​ switch关键字:表示这是一个switch语句 switch后的表达式:表示选择条件 表达式。

​ case语句:每个case 语句表示一个分支 类比于if所表示的一个分支

​ break语句:表示结束switch语句

​ default语句:表示当所有其他的case的分支,都不能匹配switch后表达式的值的时候,此时就会执行default分支。 有点类似于 if-else多分支中最后的else

注意事项

  1. switch 表达式的结果类型 表达式的取值:byte, short, int, char JDK7以后可以是:String 字符串
  2. case 后的常量取值?case后面的值,不能相同,值必须得是常量值,必须和表达式值的类型相同
  3. break可以省略吗?语法上可以省略,省略之后,switch实现的就不再是我们所期望的多分支选择结构了,会发生一个现象case穿越

​ 所谓的case穿越是指:

​ 当匹配到switch语句的某个分支,当该分支中不包含break语句,swtich语句不会自动结束,紧接着执行,紧邻的下一个case的语句体,最终要么遇到别的分支中的break;结束,要么匹配到最后一个case,结束switch语句

  1. default可以省略吗?

​ 语法上可以,一般建议不要省略,我们根据实际开发需要来决定

  1. default分支,必须只能放在最后吗?

​ 语法上没有问题,default分支可以放在switch的任意位置,注意default分支,如果不在最后,如果不加break,仍然会发生case穿越现象

  1. switch语句的结束条件

小练习

模拟做单项选择题,根据你的选择,给出对应的答案。(表达式是字符的情况)

    System.out.println("你的女神是?");
    System.out.println("A.高圆圆");
    System.out.println("B.云姐");
    System.out.println("C.沈佳宜");
    System.out.println("D.石原里美");

    Scanner sc = new Scanner(System.in);
    String s = sc.nextLine();
    char c = s.charAt(0);
    
    switch (c) {
      case 'A' :
        System.out.println("您的女神是:高圆圆");
        break;
      case 'B' :
        System.out.println("您的女神是:云姐");
        break;
      case 'C' :
        System.out.println("您的女神是:沈佳宜");
        break;
      case 'D' :
        System.out.println("您的女神是:石原里美");
        break;
    }

键盘录入字符串,根据给定的字符串,来输出你选择的字符串是什么?(表达式是字符串的情况)

    switch (s) {
      case "A" :
        System.out.println("您的女神是:高圆圆");
        break;
      case "B" :
        System.out.println("您的女神是:云姐");
        break;
      case "C" :
        System.out.println("您的女神是:沈佳宜");
        break;
      case "D" :
        System.out.println("您的女神是:石原里美");
        break;
    }

用switch语句实现键盘录入月份,输出对应的季节

    int month = sc.nextInt();
    switch (month) {
      case 12:
      case 1:
      case 2:
        System.out.println("冬季");
        break;
      case 3:
      case 4:
      case 5:
        System.out.println("春季");
        break;
      case 6:
      case 7:
      case 8:
        System.out.println("夏季");
        break;
      case 9:
      case 10:
      case 11:
        System.out.println("秋季");
        break;
      default:
        System.out.println("您输入了错误的月份");
    }

看程序写结果

    //1.
    int x = 2;
    int y = 3;
    switch(x){
      default:
        y++;
        break;
      case 3:
        y++;
      case 4:
        y++;
    }
    System.out.println("y="+y);

​ y = 4;

    int x = 2;
    int y = 3;
    switch(x){
      default:
        y++;
      case 3:
        y++;
      case 4:
        y++;
    }
    System.out.println("y="+y);

​ y = 6;

循环结构

​ 循环结构与顺序结构和选择结构不同,循环结构的主要功能是控制Java语句能够重复执行。

​ 循环结构,从语法上来讲,有3中实现形式:

  • for语句
  • while语句
  • do while语句

​ 但是不管哪种实现形式,都由4部分组成:

  • 初始化语句
  • 条件判断语句
  • 循环体语句
  • 循环体控制语句

for循环语句

基本格式

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

示例

    for(int i = 1; i <= 10; ++i) {
      System.out.println("hello 你好 --- " + i);
    }

注意事项

​ 1. 判断条件语句的结果的数据类型 只能是boolean

​ 2. 循环体语句

练习

请在控制台输出数据1-10

    //请在控制台输出数据 1-10 第一个数1 最后一个数10
    for (int i = 1; i <= 10; i++) {
        System.out.print(i + "\t");
    }
    System.out.println();

请在控制台输出数据10-1

    //请在控制台输出数据 1-10 第一个数10 最后一个数1
    for (int i = 10; i >= 1; i--) {
        System.out.print(i + "\t");
    }
    System.out.println();

求出1-10之间数据之和

    //求1~10之间数据的和
    int sum = 0;
    for (int i = 1; i <= 10; i++) {
        sum = sum + i;
    }
    System.out.println("1~10之间数据的和为:" + sum);

求出1-100之间偶数和

    //求 1~100之间所有偶数的和
    sum = 0;
    for (int i = 2; i <= 100; i = i + 2) {
        sum = sum + i;
    }
    System.out.println(sum);

求5的阶乘

    //求5 的阶乘
    int multi = 1;
    for (int i = 1; i <= 5; i++) {
        multi = multi * i;
    }
    System.out.println(multi);

在控制台输出所有的”水仙花数”

    //水仙花数
    for (int i = 100; i <= 999; i++) {
        //百位
        int a = i / 100;
        //十位
        int b = i % 100 / 10;
        //个位
        int c = i % 10;
        if (i == (a * a * a + b * b * b + c * c * c)) {
            System.out.print(i + "\t");
        }
    }

统计”水仙花数”共有多少个

    //水仙花数的个数
    int count = 0;
    for (int i = 100; i <= 999; i++) {
        //百位
        int a = i / 100;
        //十位
        int b = i % 100 / 10;
        //个位
        int c = i % 10;
        if (i == (a * a * a + b * b * b + c * c * c)) {
        //    System.out.print(i + "\t");
            count++;
        }
    }
    System.out.println(count);

while循环语句

基本格式

      初始化语句;
       while (条件判断语句) {
      循环体语句;
       }

联系

​ for循环和while循环的联系:

​ for循环和while循环几乎可以在任何场景下,作等价替换

​ for循环和while循环的区别:

​ 直观来说,for循环适合针对一个范围判断进行操作(循环次数比较明确),while循环适合判断次数不明确操作

练习

我国最高山峰是珠穆朗玛峰:8848m,我现在有一张足够大的纸张,厚度为:0.01m。请问,我折叠多少次,就可以保证厚度不低于珠穆朗玛峰的高度?

    //初始化语句 纸张的初始化高度
    double height = 0.01;
    int count = 0;
    while (height < 8848) {
      height *= 2;
      count++;
    }
    System.out.println("次数是:" + count + "---- height " + height);

do while循环

基本格式

    初始化语句;
    do {
     循环体语句(也包含条件控制语句);
    } while (条件判断);

示例

    //先执行循环体,在判断
    int i = 10;
    do {
      System.out.println(i);
      i++;
    } while (i > 11);

注意事项

​ do while 的while语句最后有一个 ;

​ do…while执行流程和之前的for和while稍有不同:

  1. 执行初始化语句
  2. 不管是否满足循环条件,都首先执行一次循环体中的代码
  3. 之后的执行流程就和for while 一样

三种循环比较

  1. 3种循环中,for循环和while循环等价

  2. do … while循环与其他两种循环结构相比,略有不同,因为do…while结构可保证循环体至少执行一次

注意事项

​ 实际使用时,只要达到预期的效果,用哪个都可以

​ 如非特殊情况,要注意要规避死循环问题(无限循环),如:

​ for( ; ; ) 或 while(true)

​ 死循环并非不能使用(学习多线程时解释)

练习

​ 1.请输出一个4行5列的星星(*)图案。

*****

*****

*****

*****

*****

    for(int i = 0; i < 4; i++) {
      //重复输出每一行的 *
      for (int j = 0; j < 5; j++) {
        System.out.print("*");
      }
      //换行输出下一行
      System.out.println();
    }

​ 2.请输出如下图形

*

**

***

****

*****

    for (int i = 1; i <= 5; i++) {
    
      //控制输出每一行的*
      for (int j = 1; j <= i; j++) {
        System.out.print("*");
      }
      System.out.println();
    }

​ 3.在控制台输出九九乘法表。

    for (int i = 1; i <= 9 ; i++) {
      //控制每一行输出的表达式
      for (int j = 1; j <= i ; j++) {
        //内存循环中的每一次执行,输出的是一个表达式
        System.out.print(j + "x" + i + "=" + j * i + "  ");
      }
      //换行
      System.out.println();
    }

跳转控制语句

break

用法

  • 结束单重循环
  • case语句中每个分支的结束标志
  • break带标签,可以跳出多层循环
    public class BreakDemo {

      public static void main(String[] args) {

        //break的基本功能,结束单重循环
        for (int i = 1; i <= 10; i++) {
          // 输出到5
          System.out.println(i);
          if(i == 5) {
            break;
          }
        }


        System.out.println("--------------------------------------------------------------------");
        // 终止外层循环
        outer: //给外层循环定义了个标签(标识符)
        for (int i = 0; i < 3; i++) {
          for (int j = 0; j < 3; j++) {
            if( j == 2) {
              break outer;
            }
            System.out.println("i = " + i + " -- " + "j = " + j);
          }
        }
        System.out.println("--------------------------------------------------------------------");
        //结束case的用法之前已经在switch用过,不在赘述

      }

    }

continue

用法

  • 退出循环的一次迭代
  • continue带标签,可以跳出多层循环的当前次循环
  • continue带外层标签可以等价实现break的功能
    public class ContinueDemo {

      public static void main(String[] args) {

        for (int i = 1; i <= 10; i++) {
          if(i == 5) {
            //终止,单重循环的一次循环过程
            continue;
          }
          System.out.println(i);
        }


        outer:
        for (int i = 0; i < 3; i++) {

          for (int j = 0; j < 3; j++) {
            if( j == 1) {
              continue outer;
              //break;
            }
            System.out.println("i = " + i + " -- " + "j = " + j);
          }

        }

      }

    }

return

结束当前方法的执行,不仅可以跳出循环,return后面的语句也无法执行到。

方法

定义

方法就是完成特定功能的代码块(在有些其他语 言中,也被成为函数function)

格式

    修饰符  方法返回值类型 方法名(参数1类型 参数1名称,参数2类型 参数2名称, ……) {
        方法体语句;
        return 返回值;
    }

方法定义的格式说明:

​ 修饰符:现在先认为是固定的 public static

​ 返回值类型:方法体中的代码执行结果的数据类型

​ 方法名 :标识符 参数 :类比数学中函数的自变量 z = f(x, y)

​ 方法体:实现具体功能的语句结合

​ return:跳转控制关键字 (并非必须)

​ 返回值:方法执行的到的最终结果

注意

  • 方法不调用不执行
  • 方法与方法是平级关系,不能嵌套定义
  • 方法定义的时候参数之间用逗号隔开
  • 方法调用的时候不用在传递数据类型
  • 如果方法有明确的返回值,一定要有return带回一个值
  • 方法记得多写javadoc形式的注释,更加规范

练习

键盘录入一个数据n(1<=n<=9),输出对应的nn乘法表

    public class Exercise {

      public static void main(String[] args) {
        //调用方法
        // 2 x 2乘法表
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        printMulti(n);

      }

      //定义一个方法来完成输出n x n乘法表
      public static void printMulti(int n) {
        for (int i = 1; i <= n; i++) {

          for (int j = 1; j <= i; j++) {
            System.out.print(j + "x" + i + "=" + j * i + "  ");
          }
          System.out.println();
        }
      }

    }

重载

在同一个类中,允许存在一个以上的同名方法

​ a.只要它们的参数个数

​ b.参数类型不同

​ c.参数顺序不同: 不是指形式参数的变量名顺序不同,而是指形式参数类型顺序

编译器如何区分方法呢? 通过方法签名

方法签名:方法名 + 参数列表 比如 add(int, int)

​ add(double, dobule)

示例

    public class OverLoadDemo {
        public static void main(String[] args) {
            System.out.println(add(3, 5));// 8
            System.out.println(add(3, 5, 10));// 18
            System.out.println(add(3.0, 5));// 8.0
            System.out.println(add(3, 5.0));// 8.0
            // 我们已经见过的方法的重载
            System.out.println();// 0个参数
            System.out.println(1);// 参数是1个int
            System.out.println(3.0);// 参数是1个double
        }
        /** 求和的方法 */
        public static int add(int n1, int n2) {
            int sum = n1 + n2;
            return sum;
        }
        // 方法名相同,参数个数不同,构成重载
        public static int add(int n1, int n2, int n3) {
            int sum = n1 + n2 + n3;
            return sum;
        }
        // 方法名相同,参数类型不同,构成重载
        public static double add(double n1, int n2) {
            double sum = n1 + n2;
            return sum;
        }
        // 方法名相同,参数顺序不同,构成重载
        public static double add(int n1, double n2) {
            double sum = n1 + n2;
            return sum;
        }
        //编译错误:只有返回值不同,不构成方法的重载
        public static double add(int n1, int n2) {
            double sum = n1 + n2;
            return sum;
        }
        //编译错误:只有参数名称不同,不构成方法的重载
        public static int add(int n2, int n1) {
            double sum = n1 + n2;         
            return sum;
        }  
    }

数组

定义

​ 数组是相同类型数据的有序集合。数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。其中,每一个数据称作一个元素,每个元素可以通过一个索引(下标)来访问它们。数组的三个基本特点:

  1. 长度是确定的。数组一旦被创建,它的大小就是不可以改变的。

  2. 其元素必须是相同类型,不允许出现混合类型。

  3. 数组类型可以是任何数据类型,包括基本类型和引用类型。

​ 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中存储的。

声明

数组的声明方式有两种(以一维数组为例)

    type[]   arr_name; //(推荐使用这种方式)
    type    arr_name[];

注意事项

  1. 声明的时候并没有实例化任何对象,只有在实例化数组对象时,JVM才分配空间,这时才与长度有关。

  2. 声明一个数组的时候并没有数组真正被创建。

  3. 构造一个数组,必须指定长度。

初始化

​ 数组的初始化方式总共有三种:静态初始化、动态初始化、默认初始化。

1. 静态初始化

​ 除了用new关键字来产生数组以外,还可以直接在定义数组的同时就为数组元素分配空间并赋值。

    int[] a = { 1, 2, 3 };// 静态初始化基本类型数组;
    Man[] mans = { new Man(1, 1), new Man(2, 2) };// 静态初始化引用类型数组;

2.动态初始化

​ 数组定义与为数组元素分配空间并赋值的操作分开进行。

    int[] a1 = new int[2];//动态初始化数组,先分配空间;
    a1[0]=1;//给数组元素赋值;
    a1[1]=2;//给数组元素赋值;

3.数组的默认初始化

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

    int a2[] = new int[2]; // 默认值:0,0
    boolean[] b = new boolean[2]; // 默认值:false,false
    String[] s = new String[2]; // 默认值:null, null

练习

数组遍历(依次输出数组中的每一个元素)

    public class Demo {

        public static void main(String[] args) {
            int[] arr = {1, 23, 4, 5, 6};
            traverse(arr);

        }

        //数组遍历(依次输出数组中的每一个元素)
        public static void traverse(int[] arr) {
            for (int i : arr) {
                System.out.print(i + "\t");
            }
            System.out.println();
        }
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aCrzVCYC-1586313350091)(C:\Users\魏铭志\AppData\Roaming\Typora\typora-user-images\image-20200306175113055.png)]

数组元素逆序

   //数组元素逆序
   public static void reverseOrder(int[] arr) {
       int length = arr.length;
       int[] arr2 = new int[length];
       for (int i : arr) {
           arr2[--length] = i;
       }
       for (int i = 0; i < arr.length; i++) {
           arr[i] = arr2[i];
       }
   }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PeJ93qCz-1586313350093)(C:\Users\魏铭志\AppData\Roaming\Typora\typora-user-images\image-20200306175508925.png)]

对取值范围在1~100的数据集合排序

   //对取值范围在1~100的数据集合排序
   public static void countSort(int[] arr) {
       int[] arr2 = new int[101];
       for (int i : arr) {
           arr2[i]++;
       }
       int count = 0;
       for (int i = 0; i < arr2.length; i++) {
           for (int j = 0; j < arr2[i]; j++) {
               arr[count++] = i;
           }
       }
   }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3g4OAbry-1586313350095)(C:\Users\魏铭志\AppData\Roaming\Typora\typora-user-images\image-20200306175636225.png)]

数组获取最值(获取数组中的最大值最小值)

   //这里以最大值为例
   //数组获取最值(获取数组中的最大值或最小值)
   public static int findMax(int[] arr) {
       //存取数组中的最大值
       int max = arr[0];
       for (int i : arr) {
           if (i > max) {
               max = i;
           }
       }
       return max;
   }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tCUaTyjM-1586313350097)(C:\Users\魏铭志\AppData\Roaming\Typora\typora-user-images\image-20200306175720505.png)]

数组查表法(根据键盘录入索引,查找对应星期)

   /**
    * 数组查表法(根据键盘录入索引,查找对应星期)
    *
    * @param index 1 代表星期一...7 代表星期日
    * @return
    */
   public static String findDayWeek(int index) {
       String[] daysOfWeeek = {"星期一", "星期二", "星期三",
               "星期四", "星期五", "星期六", "星期日"};
       return daysOfWeeek[index - 1];
   }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6yhSLcbN-1586313350098)(C:\Users\魏铭志\AppData\Roaming\Typora\typora-user-images\image-20200307195857106.png)]

数组元素查找(查找指定元素第一次在数组中出现的索引)

   //数组元素查找(查找指定元素第一次在数组中出现的索引)
   public static int findLocation(int[] arr, int value) {
       int index = -1;
       for (int i = 0; i < arr.length; i++) {
           if (arr[i] == value) {
               return i;
           }
       }
       return index;
   }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8g3rGwiR-1586313350100)(C:\Users\魏铭志\AppData\Roaming\Typora\typora-user-images\image-20200306175904724.png)]

二维数组

​ 多维数组可以看成以数组为元素的数组。可以有二维、三维、甚至更多维数组,但是实际开发中用的非常少。

二维数组的声明

    public class Test {
        public static void main(String[] args) {
            // Java中多维数组的声明和初始化应按从低维到高维的顺序进行
            int[][] a = new int[3][];
            a[0] = new int[2];
            a[1] = new int[4];
            a[2] = new int[3];
            // int a1[][]=new int[][4];//非法
        }
    }

二维数组的静态初始化

    public class Test {
        public static void main(String[] args) {
            int[][] a = { { 1, 2, 3 }, { 3, 4 }, { 3, 5, 6, 7 } };
            System.out.println(a[2][3]);
        }
    }

二维数组的动态初始化

    import java.util.Arrays;
    public class Test {
        public static void main(String[] args) {
            int[][] a = new int[3][];
            // a[0] = {1,2,5}; //错误,没有声明类型就初始化
            a[0] = new int[] { 1, 2 };
            a[1] = new int[] { 2, 2 };
            a[2] = new int[] { 2, 2, 3, 4 };
            System.out.println(a[2][3]);
            System.out.println(Arrays.toString(a[0]));
            System.out.println(Arrays.toString(a[1]));
            System.out.println(Arrays.toString(a[2]));
        }
    }

递归

定义

方法定义中调用方法本身的现象

递归方法的注意事项:

  • 1.递归一定要有出口!!(当满足某些特殊条件的时候,不在调用自己)
  • 2.而且出口条件一定要能达到
  • 3.次数不能太多,否则就出现 stack overflow

组成

递归结构包括两个部分:

  1. 定义递归头。解答:什么时候不调用自身方法。如果没有头,将陷入死循环,也就是递归的结束条件。

  2. 递归体。解答:什么时候需要调用自身方法。

核心思想

对于一个复杂的大规模的问题(无法直接求解的问题),可以将其转化为若干小规模的相似的子问题,只要能解决,小规模的子问题,把这些子问题的解组合起来,就形成了大规模问题的解。

练习

  1. 有三根杆子A,B,C。A杆上有 N 个 (N>1) 穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至 C 杆:
    a. 每次只能移动一个圆盘;
    b. 大盘不能叠在小盘上面。
    提示:可将圆盘临时置于 B 杆,也可将从 A 杆移出的圆盘重新移回 A 杆,但都必须遵循上述两条规则。
    问:最少要移动多少次?如何移?
public class Demo2 {

  public static void main(String[] args) {


    //测试一下我们的hanoi方法
    hanoi(4, 'A', 'C', 'B');

    System.out.println(count(4));
  }

  /*
       n表示待移动的盘片数量
       方法的返回值表示,n个盘片移动的总次数
   */
  public static int count(int n) {

    if (n == 1) {
      return 1;
    }

    return 2 * count(n - 1) + 1;
  }


  /**
   *
   * @param n     待搬运的圆盘的数量(表征汉诺塔问题的规模)
   * @param start 待搬运的这n个盘所在的杆的名称
   * @param end   这待搬运的n个盘,要搬运到的目标杆的名称
   * @param middle 在搬运这n个盘的时候,所用来辅助搬运这n个盘的杆的名称
   */
  public static void hanoi(int n, char start, char end, char middle) {

    //递归的出口条件,
    if (n == 1) {
      //当待搬运的盘片数量,足够小,直接就知道该如何搬运, 此时直接搬运完成即可,不用递归
      System.out.println(start + " -> " + end);
      return;
    }

    //第一步,首先将start杆上,最大的那个盘,之上的n-1个盘,搬运到midle杆上
    hanoi(n - 1, start, middle, end);  // 把n-1个盘片从start->middle

    //第二步,把start杆上的最大的那个盘,一步完成,搬运到目标杆上去
    System.out.println(start + " -> " + end); // 移动了一次

    //第三步,将middle杆上的剩余的n-1个盘片,以start杆为辅助,搬运到end杆上
    hanoi(n - 1, middle, end, start); // 把 n-1个盘片从middle -> end
  }

}
  1. 求n的阶乘
public class Demo4 {

  public static void main(String[] args) {

    //递归求解阶乘
    System.out.println(f(5));


    //循环求解阶乘
    System.out.println(calculateByFor(5));

  }


  /**
   * 返回值就表示n的阶乘的结果
   * @param n  阶乘的阶数
   */
  public static int f(int n) {

    //递归出口
    if (n == 1) {
      // 1的阶乘直接返回结果
      return 1;
    }

    int result = n * f(n - 1);
    return result;

  }


  /*
      用循环来求解阶乘
      n同样表示阶乘的阶数
   */

  public static int calculateByFor(int n) {
    int result = 1;

    for (int i = n; i >= 1; i--) {
      result = result * i;
    }

    return result;
  }

}

  1. 有一对兔子,从出生后第三个月开始每月生一对兔子,小兔子从第三个月开始每月也生一对兔子,假如是不死神兔,那么第20个月一共生多少对兔子?
public class Demo5 {

  public static void main(String[] args) {

    System.out.println(count(20));
    System.out.println(fibnacci(20));
    System.out.println(fibnacci2(20));

  }


  /**
   *
   * 方法返回值,求解的就是 第n个月的兔子的总数
   * @param n 表示的就是第n个月份
   */
  public static int count(int n) {
    //递归出口
    if (n == 1 || n == 2) {
      return 1;
    }

    return count(n - 1) + count(n - 2);

  }


  /*
      可以用循环的方式,来求解斐波那契额数列
   */

  public static int fibnacci(int n) {
    // 该数组中存了前n个斐波那契额数列的值
    int[] tmp = new int[n];
    //斐波那契额数列的前两个值为1
    tmp[0] = 1;
    tmp[1] = 1;

    //用循环求解
    for (int i = 2; i < n; i++) {
      tmp[i] = tmp[i - 1] + tmp[ i - 2];
    }


    return tmp[n - 1];
  }

    /*
      可以用循环的方式,来求解斐波那契额数列
   */

  public static int fibnacci2(int n) {
    //斐波那契额数列的前两个值为1
    int preOne = 1;
    int preTwo = 1;

    //最终斐波那契额第n个位置的值
    int result = -1;

    //用循环求解
    for (int i = 2; i < n; i++) {
      result = preOne + preTwo;

      //preOne和preTwo的值变成了,下一个位置的斐波那契额数的前一个和前两个位置的值
      preOne = preTwo;
      preTwo = result;
    }

    return result;

  }

}

End

发布了8 篇原创文章 · 获赞 6 · 访问量 323

猜你喜欢

转载自blog.csdn.net/qq_43587378/article/details/105381296