javaSE基础知识(走向编程的门口)— 更新完毕

时间:2022-04-01 20:59:44

前言:玩儿编程最重要的一点:不要怕麻烦,感觉是在浪费时间:

  • 能动手绝不哔哔:只要脑袋不傻,编程都是“一看就会,一练就废”,开始学的时候,就算再基础的东西都建议手敲一遍
  • 要有囫囵吞枣的精神:因为有时学习的时候,知识牵扯会很多,所以学的时候有时不懂就死记,记住这个点是这么做就行,但是记得备注好,然后学到相关知识了或者学完整个体系了,再回去把备注的地方更新(弄好为什么的原因),最后梳理在自己脑海中
  • 学完东西及时梳理知识内容,在脑海中形成自己的知识体系————写写博客、文档、文件、画画思维导图.......
  • 最后:多思、多想、多做(这个顺序都别乱)
    • 多思:学东西的时候多思考为什么是这样
    • 多想:学了东西多产生知识联想、以及把这个知识玩出自己的花样儿————敢想才能更进步————抱着把知识玩崩、把软件玩坏就行,大不了重装软件而已
    • 多做:想的、学的只是自己脑海中的东西,脑海中的东西不等于自己的东西————学会一直放在自己手里的才是真正属于自己的东西

给看我博客的人的建议:

  • 我的博客代码部分大部分都是我自己在上面手敲的,所以代码的字符编码和java集成开发编辑器的编码格式不一样
    • 所以要是有人直接拷贝我的代码,则:运行不了,甚至出现非法字符提醒,这不是我的锅,我主要是为了梳理知识 ^_^

1、Java简介——滤过,网上一大堆

1.1、需要了解的java两个机制

  • 跨平台机制:这在java刚出来的时候很牛逼,因为那时候不同的操作系统彼此不能兼容,在一个操作系统上写的程序就不能在另一个操作系统上运行,所以那时候java的这个技术出来之后,它的JVM虚拟机可以实现跨平台,因此很牛逼,现在哪个操作系统不可以兼容!
  • 垃圾回收机制:对于已经运行完的程序,无用东西(如:对象)系统会默认调用finalize()方法进行回收

2、关于Java环境搭建问题

2.1、下载JDK———Java Development Kit——即:java开发工具包

  • 最好的版本是JDK8,至于具体是JDK8.几的无所谓,这个版本最稳定,也是应用人员最多的
  • 直接在0racle官网中下载即可,注:有.exe的安装版和开源的压缩版(这个压缩版下载之后解压即可,然后就是配置环境变量的问题)
  • 下载地址:Java SE Development Kit 8 - Downloads (oracle.com) —— 选择自己对应的操作系统就行了,linux就选linux,window就选window
  • 建议:最好是自己去Oracle官网摸索着找一下

2.2、使用.exe的方式安装JDK

  • 傻瓜式安装,下一步下一步即可,当然选择安装路径的时候,可以根据自己的想法来
  • 只需:记住自己安装的路径即可
  • 建议:把所有的配置放在一个目录文件夹下(如:我的IntallationList安装目录文件夹——专门用来放安装的程序,安装一个在里面再新建对应的软件名字)
  • 注:.exe的安装方式,在安装JDK的时候,会有一个JRE需要安装,这个是一个公开的JRE,不用安装也可以,因为JDK中有JRE,JRE中有JVM,如图所示:

    javaSE基础知识(走向编程的门口)— 更新完毕

2.3、配置环境变量问题

  • JDK安装好之后,其实开发工具包已经算是弄好了,如图所示,我现在不配置环境变量,一样可以用JDK,只需要进到JDK的安装目录的bin之中,java、javac、java -version这些命令照样可以用

    javaSE基础知识(走向编程的门口)— 更新完毕

  • 但是为什么需要配置环境变量?
    • 因为每次都这样去找目录不麻烦吗?所以就需要配置环境变量,自报家门,因此说明一下:网上说的以及很多认为的安装JDK就是下载好了,然后安装,以及配置环境变量————安装JDK和配置环境变量是两码事,我下载安装好了JDK,照样可以进行相关的操作,只是很麻烦而已,所以需要配置环境变量来自报家门
  • 需要配置的环境变量以及说明(win10版本的,win7有细微区别——每一个选项弹出来的是一个框,每配置一项,使用英文输入法状态下输入 ; 这个符号,然后配置相关的东西即可 ):
    • JAVA_HOME  找到计算机—>右键,选择属性—>选择高级系统设置—>选择环境变量—>在系统变量(用户变量和系统变量的区别就是使用范围的大小,就字面意思)里面新建一个JAVA_HOME,然后路径就是JDK的安装路径,不用整到什么bin目录下,如我的:D:\IntallationList\JDK IntallationList,这样即可

     javaSE基础知识(走向编程的门口)— 更新完毕

    • path   这个就是给系统自报家门,所以在这里面只需要新建
      • 1、%JAVA_HOME%\bin
      • 2、%JAVA_HOME%\jre\bin      %%就是引用的意思,即:引用了前面配置的JAVA_HOME的目录,所以才在前面说:不需要精确到JDK的bin目录下,这样在这里直接引用不就方便多了

        javaSE基础知识(走向编程的门口)— 更新完毕

    • CLASSPATH 按如下配置就行了

      javaSE基础知识(走向编程的门口)— 更新完毕

  • 注:在这个CLASSPATH的目录中有一个 “ . ",这个符号要不要都无所谓,因为它表示的就是:从当前目录中加载class文件(是加载class文件),系统默认也是这个
  • 另外:弄好一个记得点确认

 2.4、怎么写java程序?

  • 最原生的方式——记事本
    • 在盘符中新建一个txt文件(是我文件中的 OneJava.txt这个 ),文件图标和我的不一样没关系,因为:我安装的有notepad++软件,并把默认方式设置过了,所以我的默认txt文档打开方式是notepad++
      • javaSE基础知识(走向编程的门口)— 更新完毕
    • 然后打开这个文件,写代码
      • public class OneJava{  // public class是死的,死记,然后OneJava就是这个想要创建的java程序的名字
        // 但是注意点:这是用的public修饰的,这是修饰符,不懂没关系,死记
        // 由于是public,所以这里的Onejava,即:java程序名字,必须和记事本的文件名一样(另外:注意大小写) public static void main( String[] args ) { // 这句代码是死的,不懂没关系,死记,注意:区分大小写 System.out.println( "这是第一个java程序" ); // 这是指打印这一句话
        }
        }
    • 保存之后,把这个记事本文件的txt,改成java
      • javaSE基础知识(走向编程的门口)— 更新完毕
        • 另外:保存的时候( 即:选择文件——另存为 )记得采用ANCI格式保存,因为后续用dos窗口打开,dos默认字符集是GBK
          • javaSE基础知识(走向编程的门口)— 更新完毕
    • 之后,选择这个路径,然后直接输入cmd,即:利用dos( 不认得,读"稻死"——dao,四声,就行了,咦~简直累 )窗口打开这个文件
      • 另:我的文件改成java之后换了一个样子,是因为我有java集成开发编辑器( IDEA ),所以不一样的话,没影响
        • javaSE基础知识(走向编程的门口)— 更新完毕
    • 这样就用dos窗口打开创建的java程序目录中来了
      • javaSE基础知识(走向编程的门口)— 更新完毕
    • 然后在这里面输入javac OneJava.java————OneJava.java就是创建的java文件的名字(自己也可以取,但是注意这个名字和文件中class之后的那个名字要一致就行)——这里有个小技巧,就是输入javac之后( 记得打一个空格 ),然后输入java程序文件的前面几个字母,最后按Tab键,自动补全文件名,如:我文件OneJava,直接输入javac之后,空一格,之后输一个One,直接Tab就自动帮我把文件名补上了。最后回车————另外:javac这个指令就是编译java文件的意思
      • javaSE基础知识(走向编程的门口)— 更新完毕
    • 按回车,编译之后就是这么一个样子————这表示:程序编译成功————另外:编译成功之后,会多一个.class结尾的字节码文件,这是机器文件,就是计算机能够识别的文件
      • javaSE基础知识(走向编程的门口)— 更新完毕javaSE基础知识(走向编程的门口)— 更新完毕
    • 想要立马看到结果,那就需要另一个指令————java  这个指令是执行指定程序的意思————这个指令的后面直接跟编写的java程序的名字即可,如下图:
      • javaSE基础知识(走向编程的门口)— 更新完毕

        输入完之后,直接回车,即可看到结果

题外话:

  • 首先,这种写java程序的方式其实真不想讲,也没什么好说的。我主要是用来搞知识的,不是弄这些的,但是有我联系方式的某些人,跟我扯犊子,说我的博客少内容,要修改,所以加了上面用记事本写java程序这部分( 当然有些地方细节性东西没处理好,如:语义表达不够准确,导致前后知识看起来好像有点矛盾了.......这些我会会注意订正 )
  • 其次,要是看我博客的人不会用dos窗口运行java程序的话,那就先在网上把这个搞懂( 真的是第一次接触java,是个真正的初学者的话,那就建议:用dos窗口编写java程序一个周 / 本篇基础内容都采用这种方式写java程序 )
  • 最后:IDEA编辑器、或者是其他编辑器、以及必备的什么notePad++...........之类的安装、破解这些我也不会在博客中说明怎么弄,这些通通靠自学 —— 革命靠自觉 —— 这点很重要,而且这些都是基础得不能再基础的东西,这些都不主动摸索的话,那就真的不适合干这一行!!!!!
    • 再次强调:我的初衷其实一是只为了某一个人而弄出来的,二是闲得蛋疼,所以顺便梳理知识,别人看我的博客只是其次,所以基础得动动手指就可以找到答案的事情都需要我整出来的话那就真的有点累了( 该提示的我也会提示 )
    • 当然语义性问题......即:我自身写的博客问题,我很高兴进行订正
    • 至于其他的看博客的人的自身问题这些,再给我扯犊子,我头都给你拧歪!!!!!!!!!

3、关于Java的数据类型——是存储一个指定类型的数据

      须知(强制要求):标识符的命名规范

    1、只能有数字、字母、下划线(即: _  ) 、$组成

    2、数字不能作为开始

    3、起的名字不能和Java系统的关键字冲突(就是java中已经用了的名字),如:import、this...... 

    4、多个单词组成的名字采用驼峰命名法:类名、接口名——每个单词首字母大写;方法名、属性(变量)名——第一个单词首字母小写,其余单词首字母大写

    5、需要见名知意                           

    6、最好别用中文以及拼音来命名(但在有些“特定范围内”可以使用拼音)

    7、常量名(包括静态常量)——全部字母大写,通过 _ 对其做解释

    8、包名——全部字母小写(注:别和关键字冲突,因为:关键字也是小写)

3.1、基本数据类型————注:java中和符号相关的一定是英文输入法状态下打出来的——如:双引号、单引号、括号......

   1、整型:从小到大————byte(字节型) short(短整型) int(整型) long(长整型)。大小的划分是由于冯洛伊曼提出的计算机存储机制(即:二进制)所决定的

        • 弄个例子:假如有这么一个二进制
0 1 0

1

        其中:里面的每一个数字为一个bit位

           4bit = 1 byte

        而整型里面的这个大小顺序就是:按照这个类型所拥有的多少个bit位来决定的(具体换算关系:百度,滤过)

  • 补充一点:整型数据类型的存储范围大小(虽然百度也有,但自己具体数值也记不清,所以直接记一个大概范围,在使用的时候按这个范围来用就行)
    • byte:[-128,127]
    • short:[128,3 0000]
    • int:(3 0000,21亿]
    • long:21亿+

  2、浮点型:按精确度从小到大————float(单精度浮点数) double(双精度浮点数),它的大小划分标准是根据IEEE754标准来的(简称IE754),但是这个标准有bug,即:对于冯洛伊曼的这种bit位存储“不太适合”

      • 举个例子:假如有一个数利用冯洛伊曼的这种bit位存储来存储,理论上应该是(这个数是假如的):
1 . 0 0 1 0 1 1

       这种数就会出现一种情况:就是后面那半截1011,在存储的时候,由于冯洛伊曼的bit位存储方式,位数刚好满了呢,

       也就是成为1.000000,那后面这个1011就没有位置可以放下了,所以就没了,

       所以float和double的区别就是:后面的这个尾数可以存储的更多一点,

       因此:要是在编程中见到那种有一个总是很接近于一个数,但是就是不等于的时候,不用意外,就是这个原因导致的

  3、布尔型:就两种true和false,主要就是为了判断逻辑关系的,非真即假嘛

  4、字符型:char,就是单引号''括起来的一个信息,啥都可以,如:'1'、'a‘、’$'、、、、、,只要是一个就行

3.2、引用数据类型

总之一句话:除了基本数据类型以外的数据类型都是引用数据类型(后续自定义的类也是),如:字符串String、类class(接口类interface)、注解@xxxxx、枚举enum

3.3、变量与常量

  • 额外知识:注释——指的是机器不会编译,只是对写的代码起解释说明的,给人看的
    • //    单行注释————使用了这个表明: // 后面这一行的内容不会被编译
    • /* */     多行注释————使用了这个表明:/*  这中间的内容不会被编译  */    支持写多行注释
    • /** */    文档注释———— 一般不会用到、写工具类的时候才会用,就是在程序中写的一个项目设计说明,最后把它提取出来
  • 建议:写注释的时候最好空一格再写注释(因为考虑到数据库中写注释的习惯)————如:  // 写注释

  1、变量

  • 定义:一句话——就是定义并赋值之后还可以再发生变化(至于怎么发生改变,到了构造器就知道了)
  • 声明方式与赋值:数据类型 常量名 【= 值】,【】表示不是必须有的,但是不赋值需要注意下述的注意1

举个例子

class Test{ // 这种是类的创建,先这么玩儿,到了面向对象思想编程时会做详细说明

  public static void main( String[] args ){   // 主方法入口,java运行的时候首先找的就是这个,这是死的,死记就行       

    byte b = 126;

    short s = 310000;

      
    int i = 2000000000;
    long = 2200000000L;     float f = 3.4F;  // 注:定义long 、float、double需要注意,在赋值的时候需要在数值后面加上相应数据类型的首字母
               //(大写和小写都可以,,建议大写,因为小写可能会不好区分),加这个的原因:因为赋的数值,系统默认是int类型的,
               // 所以赋的这个值原本是Long、float....类型的,但是int类型装不下,所以会造成数字异常

    double d = 9.1415D     boolean b2 = true;     char c = ‘a’;// 注:char c = ‘’;这种是不可以的( 即:单引号中什么都没有 ),会报错,但是String这么玩儿就可以


}

}
  •  注:1、变量定义在方法内部的话,必须先赋值,才能使用(即:局部变量),如:
class Test{

  public static void main( String[] args ){

    // int i;
    // System.out.println( i );// 这种不得吃,没赋值

    int m = 10;
    System.out.println( m );// 这种就得吃

  }

}
    • 2、如果变量定义在方法外部,则就算没有赋值,也可以使用,因为就算没有赋值,系统也会默认的帮忙赋值(即:全局变量),如:

class Test{

  String name;

  public static void main( String[] args ){

    System.out.println( name );// 这种得吃

    name = "邪公子";
    System.out.println( name );// 这种还得吃

  ]

}

3.3.2、常量

3.3.1、定义

  • 一句话:就是定义并赋值之后不可以再发生变化————所有访问这个常量得到的 都是这同样的值
    • 就是在数据类型前面加上一个特征修饰符final(目前就这么囫囵吞枣记就行,因为这是特征修饰符,后续在修饰符中会讲到)

举个例子:

class Test{

  final String NAME_THIS_IS_MYNAME = "邪公子"; // 这表明以后谁来访问这个name变量的时候( 注意:使用 _ 对常量名进行说明 ),这个值都是 邪公子

}

3.3.3、各个数据类型的小测试

如有一个洗浴中心:

class Test{

public static void main( String[] args ){

System.out.println( "欢迎来到悠忽洗浴中心" ); // 有一个技师
String name = “小翠儿”; // 她的工号
 int jobNumber = 520;  // 是否可以增值其他服务
  boolean anotherServiceByAddPrice = true;

       // 多少钱一晚
       double price = 120.0; // 提醒:记得打120啊

}

}

4、数据类型的转换

4.1、对于同一种大数据类型———即:都是属于基本数据类型/引用数据类型

4.1.1、小数据类型也相同(如:都是整型/浮点型)——秘诀就是小的可以转成大的(隐式转换),但是大的转成小的不可行,需要强制转换

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

    int i = 10;
    double d = i;// 这种是可以行的,因为int的bit存储位比double的小,所以小的转成大的是可以行的(大的装得下小的嘛)

    // int number = 20;
    // byte b = number;// 这种是不可行的,因为小的空间怎么可能装得下大的

    
     int number = 300;
     byte b = ( byte )number;// 这样强制转换之后就可行了

  }
}

4.1.2、其他类型之间的转换——直接强制转换即可

如:

class TypeConversion{

   public static void main( String[] args ){

      int i = 10;
      double d = ( double )i;
      System.out.println( d );

   }

}

注:强制类型转换虽然好用,但是可能会造成数据的丢失

5、运算符

5.1、算术运算符(单目运算符:是几目 是看这个运算符需要几个操作数来参与才是完整的表达式,如:+1、-1,就只需要一个操作数就完了)

+   -   *   /   %

5.2、复合赋值运算符(双目运算符)

++   --   +=   -=   *=   /=

注:++ 和 -- 运算符的问题

  • 两句话:
    • 如果对于操作数自己本身来说:如a嘛,无论是++a 还是 --a,最后a的结果都是a+1
    • 如果对于一个表达式来说(就是有操作数与运算符组成的式子),++a有及时性,即:先赋值再运算;而a - - 有延时性,即:先运算再赋值

举个例子:

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

    int m = 2,k = 4,L = 3;

    System.out.println( m++ + --k + L++ + --m - k++ + --L );// 问:答案为多少?

    /*
      分析一哈嘛  
          初始值:m = 2、k = 4、L = 3  
          进行计算(注意:数值的变化):2 + 3 + 3 + 2 - 3 + 3 = 13    所以最终结果就是13
          每一次变量运算完之后,数值的变化:
            前半截 m————从2变为3(延时性,先用初始值进行运算,再进行重新赋值)、k————从4变为3(及时性,立即赋值并参与运算)、L————从3变为4
            后半截(在前半截变化值的基础上进行变化) m————从3变为2、k————从4变为5、L————从4变为3
    *\

 }
}

5.3、关系运算符(也是双目运算符)

>   <   >=   <=  ==   !=   %=   /=

5.4、逻辑运算符

&&   ||   !  &   |   ^   <<   >>    >>>

  • &&:与运算————有假则假,如:
class Test{
  public static void main( String[] args ){

    int a = 10;
    int b = 20;

    int result = ( a > 0 ) && ( b < 0 ); // 这个结果的返回值类型  取决于 表达式中参与运算的所有数据类型的最大数据类型
                          // 即:如果a为int b为double 则:最后结果会自动提升为double类型
    System.out.println( result );

  }
}
  • ||:或运算,有真则真
  • &:按位与,也就是逻辑与的特殊情况(逻辑与发生短路了)
    • 如:前面的例子,a  < 0 && b < 0 这个式子中a < 0已经是false了,所以结果就是false(有假则假嘛),因此后面的判断直接不会执行了,后面的式子判断被短路(截胡)了,所以在这种情况下,还想判断后面的式子b < 0,则改成:a < 0 & b < 0,这样就按照位置依次判断了,也就不会产生短路与的情况了
  • | : 按位或,原理和按位与一样的
  • ^:异或运算,只要参与运算的两个表达式是相反的就得行,否则不得行,即:若,a > 0为真,b < 0为假,两个结果异或,就为真
  • <<  /  >>:按位左移/右移,这个是用的二进制,就是把数转化为二进制,然后对二进制进行左移或者右移,移动之后空格部分用0填充。
    • 另:<< 相当于是:原来的数(十进制的那个) 乘以  2 ^ 需要移动的数 次方————即:左位移之后的十进制数是什么
    • 而:>>相当于是:原来的数(十进制的那个) /  2 ^ 移动的数次幂————即:右位移之后的十进制数是多少
    • 来个例子:
      • 6 << 2 = 24 ———— 6 * 2 ^ 2 = 6 * 4 = 24
        • 6在底层中的样子
          • 00000000 00000000 00000000 00000110
        • 左移两位之后
          • 000000 00000000 00000000 0000011000
      • 右位移是一样的原理
  • >>> : 无符号右位移,就是不保留符号位,然后就和前面的>>和<<一样的原理了
    • 注:负数的符号位不会保留( 正数的原码和补码一样,所以不考虑 )
    • 来个例子:
      • -6 >>> 1
        • 11111111 11111111 11111111 11111010 ————往右移1位
        • ?11111111 11111111 11111111 1111101 ———— 这个符号位( 即:? )怎么填?
        • 011111111 11111111 11111111 11111111 ———— 无符号右移嘛,直接不保留符号位了 ,然后用0填充
    • 还是补充一下吧:
      • 计算机中不管是正数还是负数,存储形式都是以补码的形式存储的
        • 一个正数是以它的绝对值大小转化为二进制数,这就是它的原码,最高位就是符号位,正数的符号位为0,负数的符号位为1
          • 如:5的原码————是正数,所以它在底层中的存储形式就是下面这个
            • 00000000 00000000 00000000 00000101
          • -5的原码————负数的补码是:反码+1,而反码就是除了符号位不动,其他位置取反
            • 10000000 00000000 00000000 00000101 ———— 这是-5的原码
            • 11111111 11111111 11111111 11111010 ———— 这就是 -5 的反码
              • 补码是什么?——反码+1
                • 11111111 11111111 11111111 11111011 ———— 这就是 -5 的补码,也就是计算机真正存的值

5.5、三目运算符

即:      ?:

  • 这个就和if.......else....... 一样(流程控制会做详解),如:

  int result = a > 0 ?“ 这是一种结果,还可以支持已经定义好的变量,甚至其他数据类型 ”  :  " 这又是另一种结果,但是这个运算符的最终结果返回值类型 却取决于这两个值的最大数据类型 "  ———— 这里只是为了理解,所以里面的说明是字符串( 前面用的是int类型,所以这个不严谨的,只是为了理解

  • 可以参照if else语句
class Test{
  public static void main( String[] args ){

    int a = 2;

    if(a > 0){

      System.out.println( "这是其中的一种结果" );

    }else{

      System.out.println( "这又是另一种结果" );

    }

  }

}

6、流程控制

  • 有三种类型:顺序、选择、循环

6.1、顺序结构——   一句话,按照写的代码顺序从上到下执行,如:

class Test{

  public static void main( String[] args ){

    System.out.println( "你来打我啊" );
    
    System.out.println( "诶,就是来气你" );
    
    System.out.println( "嘿~就是玩儿,你能咋滴" );

  }

}

6.2、选择结构

第一种:单分支选择结构if(){}

class Test{

  public static void main( String[] args ){

    int score = 91;

    if( score > 90){

      System.out.println( "你厉害了" );

    }

  }

}

第二种:多分支选择结构:if  else语句  和  if语句嵌套

                  if(){

                  } else{

                  }

                  以及

                  if(){

                  } else if(){

                  }........

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

    // 单分支选泽结构
    int score = 91;     if( score > 60 && score < 70 ){

      System.out.println( "你还需要努力" );

    }else{

      System.out.println( "你还需要努力" );

    }

    // 多分支选择结构
    int sumScore = 100;

    if( sumScore < 60 ){

      System.out.println( "你去出家吧" );

    }else if( sumScore > 60 && sumScore < 70 ){

      System.out.println( "你还需要继续努力" );

    }else if( sumScore > 70 && sumScore < 80 ) {

      System.out.println( "你很牛" );

    }else if( sumScore > 90 && sumScore < 100 ){

      System.out.println( "你牛逼了" );

    }else if( sumScore == 100 ){

      System.out.println( "你牛逼大了" );

    }

  }

}

第三种:多分支选择结构:Switch语句

            Switch( 这里面结果可以为byte、short、int及这三个的对应包装类,包装类在工具类中会说明、char、String 这个string类型是JDK1.7的时候有的 ){

                  case 1:  

                      代码1;

                      break/continue; // break———是指:终止循环(只要是循环体中都可以用这两个关键字)

                  case 2:

                      代码2;

                       break / continue;  // continue———是指:终止本次循环,从下一次循环开始执行

                  .........

            }

如:

class Test{

  public static void main( String[] args ){

    int sumScore = 99;

    Switch( sumScore > 60 ){

      case 70:
            System.out.println( "哟西,还可以" );
            break;

      case 80;
            System.out.println( "nice,你要不得了" );
            break;

      case 90:
            ............... // 不写了,手软得很!

    }

  }

}

6.3、循环结构

1、while循环——和if语句差不多

如:有这么一个需求:需要对输入的数 的 各个位的数求和(不确定这个数有多少位),如:输入1234——sum = 1+2+3+4 = 10

import java.util.Scanner;   // 这个就是导包的意思,Java其实就是别人写好的工具罢了,所以这里就是引入别人写的java.util包下的Scanner类
                 // 这个就是为了可以键盘输入内容而已(输入的内容类型取决于int number = input.nextInt()
                 // 中的nextInt(),这个里面是int则结果就为int类型,是string则结果就是string类型


class Test{

  public static void main( String[] args ){

    System.out.println( "请输入一个数" );
    Scanner input = new Scanner( System.in );
    int number = input.nextInt();  // 以上对于用键盘输入内容的代码都是固定的,只是input和number的名字可以改而已

    int sum = 0;
    while( number != 0 ){

      int remainder = number % 10; // 输入的数 % 10 得到输入数的最后一个数字 如:1234 % 10————>得到4
      number /= 10;  // 对输入的数 进行截取————如:1234 / 10————得到123,这样就可以下一次得到3这个数字了
      sum += remainder;  // 这样就可以实现每个数相加的和 如:4+3+2+1 = 10

    }

  }

}

2、do while语句——这个语句会至少执行一次,也就是说:程序是先执行再判断满不满足条件

class Test{

  public static void main( String[] args ){

    int score = 80;
    do{

      System.out.println( “恭喜你成为最后一名了!" );

    }while( score > 90 )

  }

}

3、for循环

              for(初始值(计数器) ; 结束条件 ; 迭代表达式){

                   好多代码......

             }

class Test{

  public static void main( String[] args ){

    for( int i = 0 ; i < 10 ; i ++ ){

      System.out.print(" " + i);

      /*
        程序解读:
            i = 0,i < 10 ? 满足则继续执行后续的程序,不满足则直接不用进入本循环了(这里是满足的)
            满足条件,执行打印输出语句
            然后:i = i + 1 = 1
            后面依次类推

            最终结果为:
                 0 1 2 3 4 5 6 7 8 9
      *\
    }

  }

}

7、数组——是存储一组相同数据类型的数据

7.1、为什么要有数组?

  • 要存储数据,变量就够了,干嘛还要有数组?
    • 因为变量存储的是一个指定类型的数据,所以当数据很多的时候(如:50个、100个、1000个),这就要定义很多变量,既麻烦,又浪费存储空间,所以有了数组
  • 数组的三个特性 
    • 一致性:数组只能保存相同数据类型元素,元素的数据类型可以是任何相同的数据类型
    • 有序性:数组中的元素是有序的,通过下标访问
    • 不可变性:数组一旦初始化,则长度(数组中元素的个数)不可变

7.2、一维数组——数组中每个元素只带有一个下标

1、怎么创建并赋值?

  1.1、静态创建:即:创建这个数组的时候就赋值

  • 格式:数据类型[] 数组名字 = new 数据类型[]{值1,值2,值3....};
  • 这种方式的缺点:数组的大小已经固定了,如果后续想要改变数组的大小就无法改变了(目前是不可以,后续的技术是可以的
class Array{

  public static void main( String[] args ){

    // 第一种:
    int[] array1 = new int[]{ 1,2,3,4 };

    // 第二种
    int array2 = new int[3];
    array2 = 1; //数组默认是从下标0开始存值/取值
    array2 = 3;
    array2 = 4;
  }

}

  1.2、动态创建:即:只定义数组的数据类型和名字,但是不给赋值,后续用的时候再赋值

  • 这种创建方式稍微比较灵活一点
class Array{

  public static void main( String[] args ){

    String[] array; // 这里不赋值,后续再赋值,所以这里也就不会确定数组的大小了

    // 后续用了再赋值————加入日本的著名程序员
    array = {“苍井空”,“波多野结衣”}; // 但是这里一旦赋了值,则数组的空间大小就固定了,后续再想改就不得吃了,所以也是有弊端的

  }

}

2、数组怎么取值?——通过 数组名[下标值]

class Array{

  public static void main( String[] args ){

    int[] arrray = new int{}{ 1,2,3,4,5,6 };

    System.out.println( array[0] );
    System.out.println( array[1] );
    System.out.println( array[2] );

  }

}

3、数组的遍历———注:遍历 不等于 输出(遍历是指去访问一遍,输出是把它访问了打印出来,所以这两个是两码事儿)

  3.1、利用for循环

class ArrayEach{

  public static void main( String[] args ){

    int[] array = new int[]{ 5,2,0,1,3 };

    for( int i = 0 ; i < array.length ; i ++ ){

      System.out.println( array[i] );

    }

  }

}

  3.2、利用增强for

  3.2.1、什么是增强for?

             for( 数据类型 接收者名字 : 被接收者名字 ){

             }

举个例子:

class ArrayTest{

  public static void main( String[] args ){

    String[] array = new String[]{ "张学友“,”张家辉“,”*“ };

    for( String result : array ){  // 注意:这个接受者的数据类型 要和被接受者的数据类型一样 或者 是比被接受者的数据类型小

      System.out.println( result );

    }

  }

}

7.4、数组的扩容——本质就是利用数据的拷贝

  第一种方法:自己写流程来进行扩容

class ExpansionArray1{
  
  public static void expansion{  // 这是定义了一个方法,后续面向对象思想编程会做详细说明————扩容的思想是下面的
    
     // 1、数组的初始长度
    int[] array = {1,2,3,4};
    
    int[] newArray = new newArray[ array.length * 2 ];

    // 2、实现数据拷贝
    for( int i = 0 ; i < array.length ; i ++ ){

      newArray[i] = array[i]

    }

    // 3、实现地址交换————即:重命名,这样别人看起来就是扩容了
    array = newArray;
  }

}

  第二种方法——白嫖,利用别人写好的:调用System.arraycopy()方法

class ExpansionArray2{
   
  public static void main( String[] args ){
    
  // 旧数组的开始长度
  int array = { 1,2,3,4 };

  
  // 参数说明:       旧数组名字   从旧数组的哪个位置开始复制  新数组名字   从新数组哪个位置开始    复制旧数组的多少个元素
  // void arraycopy( Object src, int srcPos, Object dest, int destPos, int length );
  // 注意:这个方法没有返回值,是void修饰的————目前这么记,到了面向对象层面就可以懂方法、返回值、参数这些了

  // 实现数组扩容并实现数组地址交换
  int[] newArray;
  array = System.arraycopy( array , 0 , newArray , 0 , array.length );

  }

}

  第三种方法——还是白嫖,一样利用别人写好的——Arrays.copyOf():这个方法有重载的,看需要来决定用哪一个——重载就是这个copyOf()名字都是一样的,在面向对象中会做详解

class Expansion3{
  
  public static void main( String[] args ){
    
  // 旧数组初始长度
  int[] array = {1,2,3,4};

  // 实现数组扩容并实现地址交换
  array = Arrays.copyOd( array , 5 ); // 参数说明:第一个参数为——旧数组的名字  第二个参数为——想要创建的新数组大小
                       // 这个方法底层采用的原理就是第二个方法的设计原理
  }

}

7.3、二维数组——二维数组的本质其实就是一维数组,是一维数组的特殊数组,可以看成是一维数组中套了一层一维数组

    实际开发中很少用(了解即可)

1、创建与赋值

和一维数组一样,有着静态创建和动态创建

  • 静态创建:一样的在创建的时候就把数组的大小确定了
class Array{

  public static void main( String[] args ){

    // 第一种静态创建
    int[][] array = new int[][]{ {1,2},{3,4} };   // [][]可以理解为是几行几列(虽然严格来说这么想不对,但是可以这么想,等到new 对象的原理分析时就懂了,二者一样)

    // 第二种静态创建
    short[][] array2 = new short[3][4];

    // 第三种静态创建————只给一部分的数组大小
    byte[][] array3 = new byte[3][];
    byte[][] array4 = new byte[][4]; // 注:这种是不得吃的
  }

}
  • 动态创建:一样的才创建的时候不给数组的具体大小,后续需要用的时候再赋值
class Array{

  public static void main( String[] args ){

    int[][] array;

    // 后续用到了,然后就可以进行赋值————缺点:也是一旦赋值了后续再想改数组大小就不得吃了
    array = { {2,3},{5,5} };

  }

}

后续的和一维数组是一样的东西

8、来几个好玩的,锻炼一下脑袋————对数组里面的元素进行排序

8.1、冒泡排序

  • 思想:
    • 排序的思想是怎么样的?————以数组索引的顺序 依次和后一个元素进行两两比较,前一个数比后一个数大就彼此换位,这样一个轮回下来 就可以让最大的那个数成为数组的最后一个了(一个轮回做的事情)
  • 思考实现方式:
    • 首先按一个轮回的思想来做:这样一共要进行多少轮?————数组的长度是多少就是多少轮
    • 然后就是:怎么知道已经进行了多少个轮回?————数组的长度 - 1(去除第一个轮回排出来的这一轮)- i(i的大小就是已经进行了多少个轮回,即:已经排好了几个数)
public class BubbleSort{

    public static void main( String[] args ) {

     // 要求对这个数组进行升序排列
int[] array = { 3, 5, 6, 2, 7, 1, 9, 0 };


    // 实现方式:

// 控制总的趟数(轮回数)
for ( int i = 0 ; i < array.length ; i++ ) { // 控制每一趟(每一个轮回)
for ( int j = 0; j < array.length - 1 - i; j++ ) { // 每一个轮回需要做的事情————打擂台————两两比较
if ( array[j] > array[j + 1] ) {  // 要进行降序排列的话  把这里的 > 改成 < 即可

int temp = array[j];
array[j] = array[j + 1];
array[j+1] = temp;

} }

} System.out.println( Arrays.toString( array ) ); // Array.toString()是一个工具类 用来对数组进行转换的————转换成我们人可以看得懂的,不然直接进行
                                // 输出array。那得到的就是一个地址码 }

}

插入一个编程思想在现实中发生的————就当愉悦心情嘛

  • 在上面的冒泡排序中有一个变量换位的思想
    • 即:源码
      • int temp = array[j];
        array[j] = array[j + 1];
        array[j+1] = temp;
  •  这是一种换位的思想嘛————所以来个面试题
    • 假如去华为面试,有这么一个问题:
      • 一头牛重15kg,这头牛准备过一座桥,而这座桥只能承重10kg,问:利用编程的思想,怎么把这头牛弄过桥?
      • 答案:
        • 把这头牛卖了
        • 买一部华为手机,然后把这部手机带过桥
        • 因为:华为手机就是牛 ^ _ ^

8.2、选择排序

  • 思想:
    • 假设数组中的第一个数为最小的数(把这个数当做是已经排好了)
    • 然后从后面没有排好的数之中,依数组顺序去另外的数,和假设的这个最小数进行比较
      • 如果有比假设的这个数更小的,则标记那个更小的数 的 索引值(即:下标)
        • 另外:在找寻更小的数时,只是临时更新那个更小数的索引值,要继续找寻下去,若:有比更新的那个数 更要小的,则:记录的索引值又更新为这个更加小的索引值
    • 到一轮结束之后:记录的索引值 对应的元素就是这个数组中 余下那些还未排序的数 的最小数
    • 最后把找到的这个最小数 和 第一步自己假设的最小数 进行换位————这样就得到前面排好的数就是升序排列了

代码实现:

class SelectSort{

  public static void main( String[] args ){

      // 对这个数组进行升序排列
      int[] arr = { 3,2,7,5,4,1,9,8,0 };

      // 代码实现

    // 1、把每个数都假设一遍:让它成为最小的数
for ( int i = 0; i < arr.length; i++ ) {

// 先假设第i个数为最小的数(刚进入循环时i = 0 就是指数组的第一个数),记录它的索引
int min = i;

// 2、控制每一趟做的事情
for ( int j = i + 1; j < arr.length; j++ ) {  // i + 1 就是假设第一个数为已经排好的数

// 若里面有其他数比假设的最小数还小
if ( arr[min] > arr[j] ) {  // 要想实现降序排列 修改这里

// 更新最小值的索引值
min = j;

}

} // 3、验证一下:如果有比假设的数更小的————看看假设的数 的索引值有没有产生变化————有的话两个数就进行换位
if ( min != i ) {

int temp = arr[min];
arr[min] = arr[i]; // 有比假设的最小数更小的话,则:这里的min在前面的if语句中(即:min = j语句)更新了
arr[i] = temp;

}

}

    // 打印输出
    System.out.println( Arrays.toString( arr ) );

  }

}

8.3、插入排序

  • 思想:
    • 假设数组中的第一个数排好的(已排序区)
    • 依次用后面未排序区的数值 和 已排序区的数值进行比较
    • 如果未排序区中的数值 比 已排序区中 的数值小,则:二者进行换位———— 一个轮回完毕
    • 依此思想进行循环,直到完全排好序

package cn.xieGongzi.arrayStudy.sortStudy;

import java.util.Arrays;

/**
* 插入排序学习
*/
public class InsertSortStudy {

public static void main(String[] args){

// 对这个数组进行升序排列
int[] array = { 3,5,2,7,4,8,1 };

// 实现方法————优化版的
for( int i=1; i < array.length; i++ ){

//保存每次需要插入的那个数
int temp = array[i];
int j;

//把大于需要插入的数往后移动。最后不大于temp的数就空出来j
for( j=i; j>0 && array[j-1]>temp; j-- ){

array[j] = array[j-1];

}

array[j] = temp;//将需要插入的数放入这个位置

}

System.out.println( Arrays.toString(array) );

}

}