zoukankan      html  css  js  c++  java
  • Java基础

    java基础

    类(class)语法元素

    public class HelloWorld{

    }

    public class 是类修饰词

    helloWorld是类名,要与文件名一致

    大括号内是类得内容


    main方法(main method)语法元素

    public class HelloWorld{
     public static void main(string[] args){

    }
    }

    public static void是方法修饰词

    小括号内是方法的参数(parameter)

    String[] args是方法参数

    大括号内是方法的内容,又称方法体(method body)

    Main方法最为特殊的一点是,它是java程序的入口,就好像游戏的开始按键


    System.out.println

    public class HelloWorld{
     public static void main(String[] args){
       System.out.println();
    }
    }

    System.out.println 是java平台提供的类库内容,可以将内容输出到标注输出,在我们的例子里,就是命令行(commandline)

    小括号里的内容还是参数列表

    没有参数的情况下,System.out.println会输出一行空行,也就是类似我们桥下一个回车键


    字符串

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

    在java里,双引号引起来的内容叫一个字符串

    字符串不是语法内容,可以写任意字符


    初识java程序

    初识class

    java语言中的一等公民,java程序就是一个个的类的组成的

    类由修饰符,类名和类的内容组成

    类名必须与保存的类原文件的内容相同

    初识main方法

    main方法是Java程序执行的入口

    方法由放大修饰符,方法名,参数列白和方法体等组成

     


    从加减乘除到变量

    计算加减乘除

    字面值

    加减乘除运算符

    public class test1 {
       public static void main(String[] args) {
           System.out.println(5 + 6);
           System.out.println(5 - 6);
           System.out.println(5 * 6);
           System.out.println(5 / 6.0);

           System.out.println(1 + 2 * 3 / 4.0 + (5 + 6) / 7.0);
      }
    }

     

    基本数据类型——int

    java中所有的数据都有类型,类型决定了存储的形式和占用的存储空间。举个例子:

    微博

    博客

    连载小说

    int用来表示一个整数,取值范围在 -2^31 ~ 2^31-1。计算出来是-2147483648 ~ 2147483647

    关键字(key word)和标识符(Identifier)

    标识符:

    由大小写英文字符,数字和下划线_组成的,区分大小写的,不以数字开头的文字

    可以用作Java中的各种东西的名字,比如类名,方法名等

    标识符是区分大小写的

    关键字是Java语法的保留字,不呢个用来命名

    用变量解决问题

    变量

    如何创建变量

    如何给变量一个值

    如何使用变量

     

    public class test1 {
       public static void main(String[] args){
           int a = 1;
           int b = 2;
           int c = 3;

           int x = 0;

           int y = a * x + b * (x * x) + c * (x * x * x);

           System.out.println(y);
      }
    }

     


    从加减乘除到变量和语句

    java代码三级跳——表达式,语句和代码块

    表达式(expression):Java中最基本的一个运算。比如一个假发运算表达式。1+2是一个表达式,a+b也是

    语句(statement):类似于平时说话时的一句话,由表达式组成,以;结束。1+2;1+2+3;a+b;都是语句

    代码块:一对大括号括起来就是一个代码块

    Java是区分大小写的

    关键字和标识符都是区分大小写的

    类名必须与文件名一致,包括大小写要求

    使用变量时,名字必须和声明时的标识符大小写一致

    方法名也区分大小写。main和Main是两个名字

    类型也区分大小写。int是数据类型,Int不是

    System.out.println可以呗Java认识,SYSTEM.Out.Println就不行

    字面值不简单

    整数的字面值类型默认是int

    十六进制字面值和八进制字面值

    超过int的范围会怎么样?需要使用范围更大的类型

    int x=5;int y=x+1;包含了多少语法点

    int x = 5;

    关键字、标识符、运算符、字面值、数据类型,Java中的数据都有类型,数据类型有其取值范围、变量的创建和赋值

    int y=x+1;

    变量的使用,标识符区分大小写、加法运算符、表达式,语句和代码块


    Java中的基本数据类型

    认识二进制

    十进制:每一位可以是0~9这10个值,到10进位一百用十进制表示就是100

    二进制:每一位可以是0、1,到2进位,100用二进制表示就是1100100,十就是1010

    十六进制:每一位可以是0~F这15个值,到16进位,一百用16进制就是64,十就是A

    bit和byte:

    一个二进制的位叫做一个bit,俗称小b,宽带中的单位都是小b

    八个二进制的单位,组成一个byte,俗称大B,硬盘等存储的单位,都是大B

    Byte是计算机中最基本的衡量存储的单位,计算机在对外使用时不会用小b作为划分存储单位

    数字的基本数据类型

    整数类型

    byte占用1个byte,值与是-128~127

    short占用2个byte,值域是-32768~32767

    int占个byte,值域是-2147483648~2147483647,java中缺省是int型

    long占用8个byte,值域是-9223372036854774808~9223372036854774807

    浮点(小数)类型

    float 有精度,值域复杂±3402823466385288598117041834516925440

    double 精度是float的一倍,占用8个byte。Java中浮点数缺省是double类型

    符号位

    布尔和字符数据类型

    boollean占用4个byte,值域是true,false

    char占用2个byte,值域是所有字符(最多65535个)

    使用各种基本数据类型

    public class test1 {
       public static void main(String[] args){
           byte byteVar = 100;
           System.out.println(byteVar);

           short shortVar = 30000;
           System.out.println(shortVar);

           int intVar = 1000000000;
           System.out.println(intVar);

           long longVar = 80000000000L;
           System.out.println(longVar);

           float floatVar = 100.0000000666F;
           System.out.println(floatVar);

           double doubleVar = 100.0000000666;
           System.out.println(doubleVar);

           boolean booleanVar = true;
           System.out.println(booleanVar);

           char charVar = 'a';
           System.out.println(charVar);

      }
    }

     


    Java中的运算符

    什么是运算符

    运算符对一个或是多个值进行运算,并得出一个运算结果

    运算符的运算结果类型有的是固定的,有时候会更具被计算的值变化。比如两个int相加,结果类型就是int。两个byte相加就是byte

    除赋值运算符外,运算符本身不会改变变量的值

    取模运算符

    用来计算余数

    负数也可以被取模

    负数也可以取模

    小数也可以取模

    整数的除法运算

    int除以int还是int,不会变成浮点数

    比较运算符和布尔运算符

    比较运算符:

    >、>=、<、<=、!=、==

    布尔运算符

    !、&、&&、|、||

    小括号运算符

    小括号运算符内可以包含任何运算符,决定运算符顺序

    运算符优先级

    ()

    *、/、%

    +、—

    >=、<、<=

    ==

    !=、

    &、&&、|、||

    =


     

    Java中的位运算符

    字面值的八进制和16进制

    以0开头的整数为8进制

    以0x开头的是16进制

    按位运算

    并:&

    或:|

    异或:^

    取反:~

    位移运算符

    >>:符号位不动,其余位右移,符号位后边补零,又称带符号位移

    >>>:符号位一起右移左边补0,又称无符号右移

    <<:左移,右边补0,左移没有带符号这么一说,应为符号在最左端

    位移运算符不会改变原变量的值

    按位运算和位移运算都不会改变原本的变量的值

    位移运算符的用处

    按位运算:掩码

    位移运算符:高效除2


    基本数据类型的更多语法点

    变量要先赋值后使用

    不给变量赋值代表什么

    声明变量

    不赋值使用会怎么样

    占用内存,报错

    计算并赋值运算符

    使代码更简洁,如a = a + 10,简化为a+=10

    +=、-=、/=、*=、%=、&=、^=、|=、<<=、>>=、>>>=

    数据类型自动转换

    不会出现问题的类型转换,编程语言可以做自动类型转化,比如低精度向高精度转换,可以发生再算数运算,也可能发生再赋值

    数值精度排序

    double>float>long>int>short>byte

    char可以转换为int

    应为char是无符号数,所以不可以自动转换为short

    强制数据类型转换

    可能出现问题的类型转换,需要使用强制类型转换,比如高精度向低精度转换、强制类型转换也是操作符、语法是用小括号括起目标类型放在被转换值得前面,强制类型转换会造成数据精度丢失

    (目标类型) 值

    数值溢出

    数值计算一旦已排除,结果失去意义,比如两个正数加出负数,要对值有大概的估计

    从数值计算溢出理解程序员和编程语言责任得分界线

    编程语言按照语法和计算机交互,程序员理解问题,并转换为程序,程序员解决问题

    字符集编码和字符串

    什么是字符集和编码

    什么是字符集(Charset):

    字符得集合,一般会包含一种语言的字符。比如GBK,是包含所有常用汉字字符的字符集,ASCII是包含英文字符的字符集,字符就是Java中的char是charset的简写

    什么是编码:

    char代表一个字符,char的本质也是数字,将数字映射道字符,就叫编码。编码是有标准的

    编码和字符集介绍

    常用字符集介绍

    ASCII码,ASCII表

    Unicode 包含世界上所有常用字符,编码也有几种,包括UTF-8,UTF-16

    Unicode,GBK等所有常用字符集,都会兼容ASCII。举个例子,字符A再这些字符集中都是对应数字65

    Java中的字符集

    Java中是UTF-16的Unicode

    当把char转换成数字时需要使用int

    ASCII码和转义符(escape character)

    如何输出特殊字符

    ASCII码+char,将这个数字转换成char,然后输出

    转义符。转义符用来给字符赋值,也可以用在字符串里面,作为字符串中的一个字符

    转义符语法和常用转义符

    ,换行符

    ",双引号

    ,制表符

    uXXXX,unicode编码对应的字符

    字符串的拼接

    将变量穿插在字符串中输出

    字符串可以和任何类型进行加法运算,会将这个值拼接道字符串上。可以使用+=操作符进行拼接

    字符串不是Java中的基本数据类型(String类)

    字符串类型的名字叫做String

    可以使用String str = "abc"来创建

    String不是Java中的保留字

    String的拼接不会改变原String变量的值,改变其值要使用赋值语句


    打印26个连续的字符

    public class test1 {
       public static void main(String[] args){
           char ch = 'A';
           int num = ch;
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));
           System.out.println(num + " " + ((char) num++));

      }
    }

     


    程序执行流程

    if-else语句

    代码块是顺序执行的,只要不报错就会一行行的进行下去

    if(boolean值){
     if语句块
    }else{
    else语句块
    }

    if-else语法只有一个语句被执行

    都是Java中的关键字

    把if-else看做一个表达式,整体还是顺序执行

    if-else的嵌套

    if-else的简化

    if-else省略大括号

    如果if或else的语句块只有一个语句,可以省略大括号

    if (boolean值)
    if语句块
    else
       else语句块
    if (boolean值){
       if语句块
    }else if(){
    if语句块
    }else{
    else语句块
    }

    for语句

    让程序在满足某条件时,重复执行某个代码块,for是关键字

    初始语句在for循环开始前执行一次,以后不再执行;循环体条件表达式在每次循环体执行前会执行,如果为true,则执行循环体,否则循环结束;循环体后语句会在每次循环执行后被执行

    for (初始语句;循环体条件表达式;循环体后语句){
    for循环体
    }

    Break语句

    break语句可以结束循环

    Continue语句

    跳过不符合条件的循环,结束当此循环的执行,开始下一次循环体的执行

    代码块和变量的作用域

    大括号括起开的就是代码块,代码块也叫体,可以嵌套

    变量的作用域

    代码块里使用外层代码块的变量

    代码块里创建变量

    不能在外层代码里使用内层的代码块变量,是否可以使用变量,也称作某个代码的可见性。也就是说,外层代码块创建的变量对内层代码块可见,内层的不对外层可见

    内层命名空间不可以重复定义外层代码块的变量,但是可以使用外层代码块的变量

    代码块无论嵌套多少层,都要遵守上述变量的可见性

    理解作用域和作用空间

    同一个命名空间中的变量不可以重名

    为了避免变量名冲突,所以必须有命名空间

    While语句

    语法:

    条件表达式的结果是一个boolean值,如果为true,则执行循环体,如果为Flase,则循环结束,可以嵌套

    while (条件表达式){
    while循环体
    }

    do-while语句

    至少执行一次

    do{
    while 循环体
    }while(条件表达式)

    死循环(endless loop)

    无法结束的循环(endless loop/infinite loop)

    没有设置好结束条件,要充分考虑各种边界情况

    switch语句

    switch(用于比较的int值){
    case 目标1,对应一个if else(xxxx);
    case 目标2,不可以与别的case字句重复;
    default (对应最后的esle,可选);
    }

    可以嵌套

    switch语句中用于比较的值,必须是int类型

    switch语句适用于有固定多个目标值匹配,然后执行不同的逻辑的情况

    必须使用一个break语句显示的结束一个case语句,否则会一直执行下去

    default子句是可选的,如果所有的case语句都没有匹配上,才会执行default中的代码

    Java中的单行注释

    以//为开始,到这一行结束都是注释内容

    注释可以说任何内容

    可以在一行的开始注释,也可以在程序后面添加,注释不会对程序有任何影响

    新功能

    生成规定范围内的随机数

    Math.random()生成随机数

    得到随机数,Java支持得到0到1之间的double类型随机数

    标准输入:

    Scanner in = new Scanner(system.in)

    连接标准输入

    in.nextLine()从命令行读取一行字符串

    in.nextint()可以从命令行读取一个整数

    import java,.util.Scanner;告诉程序这个Scanner这个类型在哪里

    数组

    数组是相同类型的变量的集合,所有元素的类型都一样

    可以指定数组包含的元素的个数,最多为int的最大值个

    元素有固定的顺序

    每个元素都有一个固定的编号,称之为索引(index),从0开始递增,类型为int

    可以像操作变量一样读写数组中的任何一个元素

    创建和使用一个数组的语法

    数组元素类型[] 变量名 = new 数组元素类型[数组长度]
    变量名[索引] 可以使用这个变量,可以读取,也可以给他赋值

    变量和数组

    重新认识基本类型的变量

    变量的基本逻辑——有定才有变。对人来说,固定的是名字,变化的是对应得值,对于计算机来说,固定得是地址,变化的是值

    理解计算机如何使用内存:

    内存就是一堆白纸,只能通过页码编号访问,也就是所谓的内存地址

    变量就是使用一个固定的地址加上对应的内存,计算机通过地址对变量进行赋值和访问。变量的名就是地址,变量的实就是值

    理解数组的名与实

    数组的实是一块地址连续的内存,就像是编号连续的白纸一样

    数组的名,就是这个块连续内存的第一个内存地址数组的变量和基本变量一样,本身是个地址。但是与基本变量不一样的是,这个地址的值,是数组的名,也就是数组的第一个值

    数组 = 数组变量+数组实体

    数组变量[索引]就是再数组原有地址的基础上加上索引,获到想要的元素

    所以索引是从0开始的,因为数组变量的地址就是数组第一个元素的地址,不需要加

    数组的长度

    数组变量.length可以获得数组的长度

    数组创建之后,长度不可改变

    数组索引过界和初始值

    抛出IndexOutOfBoundException的异常

    索引从0开始

    数组每个元素都有初始值,初始值和类型有关。对于数字类型,初始值是0,对于boolean类型,初始值是false

    让变量指向新的数组

    数组变量可以指向新的数组实体。这时候,数组变量的值就是新的数组实体的地址了。这种数组变量的赋值操作,叫做让变量指向新的数组

    如果没有别的数组变量指向原来的数组实体,也就是说,如果没有数组变量记得原来数组的地址,原来的数组实体就再也不可以访问了,好像消失了

    对于非基本类型的变量,计算机都要通过这种“两级跳”的方式来访问,基本类型变量,一跳就可以

    多维数组

    创建一个二维数组,二维数组是一维数组的自然延申

    类型 [][] 变量名 = new 类型[][]

     


    类(class)

    用来描述同一类事物,可以在内部定义任意数量的、不同类型的变量。这种属性叫做成员变量(member variable)。有类名必须和文件名一致

    语法:

    public class Merchandise {
       String name;
       String id;
       int count;
       double price;

    }

    类和对象(Instance/Object)

    如何创建对象/实例

    通过点操作符操作对象属性

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

           // >> TODO 使用new操作符,可以创建一个类的实例/对象( instance/object )。
           // >> TODO 使用new创建一个类的实例后,类中定义的每种变量都会被赋以其类型的初始值。
           //   TODO 这个和数组也是一样的
           // >> TODO 使用一个同类型的对象变量,可以指向并操作这个实例。这两点和数组都很类似
           // 创建一个Merchandise的实例,用m1指向它。
           Merchandise m1 = new Merchandise();
           // 使用点操作符,给m1指向的实例赋值。
           m1.name = "茉莉花茶包 20 包";
           m1.id = "000099518";
           m1.count = 1000;
           m1.price = 99.9;

           Merchandise m2 = new Merchandise();
           m2.name = "可口可乐 330ml";
           m2.id = "000099519";
           m2.count = 1000;
           m2.price = 3.0;


           // 卖出一个商品1
           int m1ToSold = 1;
           System.out.println("感谢购买" + m1ToSold + "个" + m1.name + "。商品单价为"
                   + m1.price + "。消费总价为" + m1.price * m1ToSold + "。");
           m1.count -= m1ToSold;
           System.out.println(m1.id + "剩余的库存数量为" + m1.count);

           // 卖出3个商品2
           int m2ToSold = 3;
           System.out.println("感谢购买" + m2ToSold + "个" + m2.name + "。商品单价为"
                   + m2.price + "。消费总价为" + m2.price * m2ToSold + "。");
           m2.count -= m2ToSold;
           System.out.println(m2.id + "剩余的库存数量为" + m2.count);


      }
    }

    认识引用(reference)类型

    java中数据类型分为基本数据类型和引用数据类型

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

           // >> TODO m1是一个Merchandise类型的引用,只能指向Merchandise类型的实例
           // >> TODO 引用数据类型变量包含两部分信息:类型和实例。也就是说,
           //   TODO 每一个引用数据类型的变量(简称引用),都是指向某个类( class /自定义类型)
           //   TODO 的一个实例/对象(instance / object)。不同类型的引用在Java的世界里都是引用。
           // >> TODO 引用的类型信息在创建时就已经确定,可以通过给引用赋值,让其指向不同的实例.
           //         比如 m1 就是Merchandise类型,只能指向Merchandise的实例。
           Merchandise m1;
           m1 = new Merchandise();
           Merchandise m2 = new Merchandise();
           Merchandise m3 = new Merchandise();
           Merchandise m4 = new Merchandise();
           Merchandise m5 = new Merchandise();

           // >> TODO 给一个引用赋值,则两者的类型必须一样。m5可以给m1赋值,因为他们类型是一样的
           m1 = m5;

           System.out.println("m1=" + m1);
           System.out.println("m2=" + m2);
           System.out.println("m3=" + m3);
           System.out.println("m4=" + m4);
           System.out.println("m5=" + m5);

           Merchandise m6 = m1;
           System.out.println("m6=" + m6);
           m6 = m5;
           System.out.println("m6=" + m6);


           System.out.println("m1=" + m1);
           System.out.println("m2=" + m2);
           System.out.println("m3=" + m3);
           System.out.println("m4=" + m4);
           System.out.println("m5=" + m5);


           int a = 999;

      }
    }

     

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

    引用数据类型和基本数据类型的相同点:都可以用来创建变量,可以赋值和使用值,本身都是一个地址

    不同点:基本类型的值就是值,引用的值是一个地址,需要通过二级跳找到实例,引用数据类型是java的一种内部类型,是对所有自定义和数组引用的统称,并非特指某种类型

    类对象和引用的关系

    引用必须是、只能是一个类的引用,引用只能指向其所属的类型的对象

    相同类型的引用之间可以赋值,只能通过指向一个对象的引用,来操作一个对象

    数组类型

    数组是一种特殊的类

    引用的数组

    可以把类名当成自定义类型,定义引用的数组,甚至多维数组

    引用的缺省值null

    null代表空,不存在。可以读做空,引用类型的数组创建出来,初始值都是空

    null带来的问题,NullPointerException(NPE)异常,如果不确定要先判空

    java中的包和访问修饰符

    为了避免在一起混乱,可以把类放在文件夹里,这时就需要用package语句告诉java这个类在哪个包里。package语句要和源文件的目录完全对应。一般来讲,类都会在包里。不同的包可以有相同的名字类型。一个类只能有一个package语句,如果有,则必须是类的第一行有效代码

    类使用太繁琐怎么办?用import

    当使用另一个包里的类时候,需要带上包名

    import语句可以有多个,如果需要一个包中的很多类,可以使用*通配符

    属性访问修饰符:public

    被public修饰的属性,可以被任意包中的类访问

    没有访问修饰词的属性,称作缺省值的访问修饰符,可以被本包内的其他类和自己的对象

    访问修饰符是一种限制或者允许属性访问的修饰符

    类的全限定名

    包名+类名 = 类的全限定名。简称类的全名

    同一个java程序中的全限定名不可重复

    Java的世界是一个类和对象的世界

    java就是使用类来描述世界,用类的实例(对象)让世界运作起来

    Intellij调试程序

    debug:不要让程序一闪而过

    设置断点,debug调试模式运行程序

    断点(breakpoint):可以让程序在调试模式停在某一行

    用断点调试程序

    Frame视图和Variable试图

    程序调试的标准动作

    查看变量的值,展开实例看内部成员变量的值

    程序执行 Step Over:执行一行

    程序继续执行:Resume,继续执行到遇到下一个断点

    Step Out执行到代码结束

    Evaluate Expression在对话框输入代码,直接执行看结果值

    条件断点:给断点设置条件,满足条件断点执行

    返回值

    参数

    参数和返回值怎么传递的

    参数和方法里的局部变量可以认为是一样的东西。只是在方法调用之前,会用实参给参数的形参赋值

    发生在代码块里的,就让它留在代码块里。方法执行完毕,参数和方法的局部变量的数据就会被删除回收。

    调用一个有返回值的方法时,就好像访问一个成员变量

    参数、局部变量的作用域

    局部变量就是我们之前说的变量,是在方法体中创建的变量

    对象是实体/实例,不是变量。创建后存放在堆中,方法里创建的对象是不会随着方法的结束被清除的,只要有引用指向一个对象,这个对象的数据就可以通过这个引用来访问

    隐藏this的自引用

    参数和局部变量重名会怎么样

    使用this:访问局部变量的完整形态

    方法

    方法描述了一类师傅的行为和功能。是对数据的操作,可以通过操控成员变量完成一个功能

    是Java中代码执行的单元,是代码的载体。所有的代码,都必须术语某一个方法

    方法就是一串语句,加上数据输入this自引用和参数,执行后得到一个返回值。所以使用一个对象调用一个方法,可以叫做调用对象的方法,也可以叫做“在这个对象上调用方法”

    方法不是对象的一部分,是类的一部分。每个对象可以给成员变量赋不同的值,但是对无法让他有不同的行为。

    可以(也只能)通过对象引用来调用

    理解方法的调用

    注释

    多行注释

    给方法加注释

    把操作成员变量的代码放在类里

    初始化成员变量

    简单访问和设置成员变量的值

    用类定义成员变量,并把操作成员变量的代码都放在类里,就是封装

    方法的签名和重载

    不同场景不同功能

    方法重载(overload)

    方法签名:方法名+依次参数类型。返回值不适于方法签名。方法签名是一个方法在一个类中的位移标识

    同一个类中方法可以重名,但是签名不可以重复。一个类如果定义了名字相同,签名不同的方法,就叫做方法的重载

    重载的参数匹配规则

    构造方法

    构造方法的重载和互相调用

    静态变量

    尽量不要使用Magic Number

    静态方法

    也叫类方法:值能使用参数个静态变量,没有this自引用

    静态方法的重载

    static代码块和static变量初始化

    方法和属性的可见性修饰符

    可见性修饰符用在类、成员方法、构造方法、静态方法和属性上,其可见性的范围一样

    Math

    Scanner

    String

    对象不可变!

    main方法和System类

    main方法也只是一个静态的,有String[]作参数的,没有返回值的方法而已。Java可以把main方法作为程序入口

    System类中有很多系统相关的方法,我们使用最多的就是in和out来读取和输出

    String类的好兄弟

    StringBuilder是一个用来拼接和处理字符串的类

    继承

    子类继承父类的方法和属性

    使用子类可以调用父类的公有方法

    使用子类的引用可以访问父类的共有属性

    就像子类的引用可以一物二用

    子类对象里藏着一个父类对象

    组合

    继承和组合的区别

    覆盖

    super

    和父类对象沟通的桥梁

    super调用父类的构造方法

    父类和子类的引用赋值关系

    父类引用可以指向子类对象,子类引用不可以指向父类对象

    可以进行强制类型转换,如果类型不对,会出错

    可以调用的方法,是受引用类型决定的

    多态到底调用的哪个方法?

    可以调用哪些方法,取决于引用类型。具体调用哪个方法,取决于所属的类是什么

    多态里的语法点

    静态多态:重载

    动态多态:覆盖

    instanceof操作符

     

    继承专属的访问控制 :portected

    = default + 对子类可见

    覆盖可以但不能让可见性更低

    final修饰词

    不可变

    继承里的静态方法

    for循环的另一种写法

    万类之祖:object类

    所有得类直接或间接继承自Object类

    hashCode和equals方法

    hashCode可以翻译成哈希码,或者散列码。应该是一个表示对象得特征值得int整数

    equals方法是判断两个对象逻辑是否相等

    toString方法

    class类

    代表类得类,每个实例都代表一个类

    反射

    使用反射(reflection)访问属性

    使用反射访问方法

    使用反射访问静态方法和属性

    面向对象三要素:封装、继承、多态

    枚举

    固定个数实例得类,枚举的父类是Enum

    接口

    让商品类型更丰富

    抽象类:接口和类得混合体

    有方法代码得接口

    静态内部类

    成员内部类

    局部内部类

    匿名类

    匿名类是用来创建接口或者抽象类得实例,匿名类可以出现再任何有代码得地方

    只能实现/继承一个接口/抽象类,本身没有名字

    如果是再成员方法或者给成员方法赋值是创建匿名类,那么会有对外部对象得this自引用

    匿名类可以访问外部类得private属性

    一个运转得超市

    ShoppingAppMain

    package com.geekbang.supermarket;

    import com.geekbang.supermarket.impl.SimpleShopman;
    import com.geekbang.supermarket.interfaces.Customer;
    import com.geekbang.supermarket.interfaces.Shopman;
    import com.geekbang.supermarket.interfaces.SuperMarket;

    import static com.geekbang.supermarket.util.ShoppingUtil.*;

    public class ShoppingAppMain {
       public static void main(String[] args) {
           SuperMarket superMarket = createSuperMarket();

           Shopman shopman = new SimpleShopman(superMarket);

           boolean open = true;
           while (open) {
               new ShoppingTask(shopman).executeTask();
               output("是否继续营业?(Yes)");
               open = ! input().next().trim().equalsIgnoreCase("no");
          }

           superMarket.dailyReport();
      }

    }

    class ShoppingTask {

       private Shopman shopman;

       public ShoppingTask(Shopman shopman) {
           this.shopman = shopman;
      }

       public void executeTask() {
           Customer customer = createCustomer(true);

           shopman.serveCustomer(customer);

      }

    }

    ShoppingUtil

    放在util文件下

    package com.geekbang.supermarket.util;

    import com.geekbang.supermarket.impl.*;
    import com.geekbang.supermarket.interfaces.Category;
    import com.geekbang.supermarket.interfaces.Customer;
    import com.geekbang.supermarket.interfaces.Merchandise;
    import com.geekbang.supermarket.interfaces.SuperMarket;

    import java.util.Scanner;

    public class ShoppingUtil {

       private static final Scanner in = new Scanner(System.in);

       public static Scanner input() {
           return in;
      }

       public static void output(Object obj) {
           System.out.println(String.valueOf(obj));
      }


       public static SuperMarket createSuperMarket() {
           int merchandisePerCategory = 10;
           Merchandise[] all = new Merchandise[Category.values().length * merchandisePerCategory];

           for (Category category : Category.values()) {
               for (int i = 0; i < merchandisePerCategory; i++) {

                   double soldPrice = Math.random() * (category.getHigherPrice() - category.getLowerPrice())
                       + category.getLowerPrice();

                   double purchasePrice = soldPrice * 0.7;

                   all[category.ordinal() * merchandisePerCategory + i] = new SimpleMerchandise(
                       category.name() + i, soldPrice, purchasePrice, 200, category
                  );
              }
          }

           SimpleSuperMarket superMarket = new SimpleSuperMarket(all);
           output("请输入超市的名字:");
           String s = input().next();
           if (s.trim().length() > 0) {
               superMarket.setName(s.trim());
          }
           return superMarket;
      }

       public static Customer createCustomer(boolean auto) {
           if (auto) {
               String custId = "CUST" + (int) (Math.random() * 10000);
               Category shouldBuy = getRandomCategory();
               if (Math.random() < 0.5) {
                   return new SuiYuanCustomer(custId, shouldBuy);
              } else {
                   ThinkAndBuyCustomer ret = new ThinkAndBuyCustomer(custId, shouldBuy);
                   ret.setCard(getRandomVIPCard());
                   return ret;
              }
          }
           // TODO 思考题:允许输入一个类名,使用Class.forName(类名),获得这个类的Class实例,
           // 然后调用newInstance方法,创建这个类的实例
           return null;

      }

       public static Category getRandomCategory() {
           return Category.values()[(int) (Math.random() * 1000) % Category.values().length];
      }

       public static VIPCard getRandomVIPCard() {
           return VIPCard.values()[(int) (Math.random() * 1000) % VIPCard.values().length];
      }


    }

    接口部分:(存于interface目录下)

    Card

    package com.geekbang.supermarket.interfaces;

    /**
    * VIP卡,打折卡,赠品卡等
    */
    public interface Card {

       /**
        * 执行完毕超市自身的打折策略之后,确定了顾客需要付多少钱。
        * 然后再根据顾客是否有VIP卡,判断是否继续打折,看顾客是否有现金卡,抵扣现金。
        *
        * @param totalCost             商品的原价总价
        * @param totalCostAfterDiscount 实行完超市活动后的总价
        * @param customer               购买的顾客
        * @param shoppingCart           购物车
        * @return 优惠额,注意不是优惠后的价格
        */
       double processCardDiscount(double totalCost, double totalCostAfterDiscount,
                          Customer customer, ShoppingCart shoppingCart);


    }

    category

    package com.geekbang.supermarket.interfaces;

    /**
    * 商品的种类
    */
    public enum Category {

       FOOD(10, 300),
       COOK(200, 2000),
       SNACK(5, 100),
       CLOTHES(200, 1000),
       ELECTRIC(200, 10000);

       int lowerPrice;
       int higherPrice;

       Category(int lowerPrice, int higherPrice) {
           this.lowerPrice = lowerPrice;
           this.higherPrice = higherPrice;
      }

       public int getLowerPrice() {
           return lowerPrice;
      }

       public void setLowerPrice(int lowerPrice) {
           this.lowerPrice = lowerPrice;
      }

       public int getHigherPrice() {
           return higherPrice;
      }

       public void setHigherPrice(int higherPrice) {
           this.higherPrice = higherPrice;
      }
    }

    Customer

    package com.geekbang.supermarket.interfaces;

    public interface Customer {

       String getCustId();

       /**
        * 开始购物前的准备
        */
       void startShopping();

       /**
        * @return 顾客想购买的商品的种类
        */
       Category chooseCategory();

       /**
        * 顾客是否购买此商品
        *
        * @param merchandise 判断是否要购买的商品
        * @return 购买多少个
        */
       int buyMerchandise(Merchandise merchandise);


       /**
        * 顾客是否买够了,要结账
        *
        * @return true:要结账, false:继续逛
        */
       boolean wantToCheckout();


       /**
        * 付款
        * @param shoppingCart 此次购买的商品的购物车
        * @param totalCost   经过超市折扣策略折扣后的折后总价
        * @return 成功支付返回支付的钱,否则返回-1
        */
       double payFor(ShoppingCart shoppingCart, double totalCost);

       /**
        *
        * @return 顾客花的钱
        */
       double getMoneySpent();

    }

    discout部分

    package com.geekbang.supermarket.interfaces;


    // >> TODO 某一个中类的商品,满多少减多少
    // >> TODO 某一个中类的商品,第二件半价

    /**
    * 超市的折扣策略
    */
    public interface DiscountStrategy {

       /**
        * @param shoppingCart
        * @return 因为此折扣策略所折扣掉的钱,注意并非折扣的总价。
        */
       double discount(ShoppingCart shoppingCart);

    }

    hashcard

    package com.geekbang.supermarket.interfaces;

    public interface HasCard {
       Card getCard();
    }

    merchandise

    package com.geekbang.supermarket.interfaces;

    public interface Merchandise {

       String getName();

       double getSoldPrice();

       double getPurchasePrice();

       int buy(int count);

       void putBack(int count);

       Category getCategory();

       int getCount();
    }

    shopman

    package com.geekbang.supermarket.interfaces;

    public interface Shopman {

       void serveCustomer(Customer customer);

    }

    shoppingcart

    package com.geekbang.supermarket.interfaces;

    import java.util.Date;

    public class ShoppingCart {

       private Merchandise[] buy;
       private int[] count;
       private int curr;
       private int max;

       public ShoppingCart(int maxTypeToBuy) {
           buy = new Merchandise[maxTypeToBuy];
           count = new int[maxTypeToBuy];
           max = maxTypeToBuy;
           curr = 0;
      }

       public boolean canHold() {
           return curr < max;
      }

       public boolean add(Merchandise m, int countToBuy) {
           if (!canHold()) {
               return false;
          }
           buy[curr] = m;
           this.count[curr] = countToBuy;
           curr++;
           m.buy(countToBuy);
           return true;
      }

       public double calculateOriginCost() {
           double ret = 0;
           int pos = -1;
           for (Merchandise m : buy) {
               pos++;
               if (m == null) {
                   continue;
              }
               ret += m.getPurchasePrice() * count[pos];
          }
           return ret;
      }

       @Override
       public String toString() {
           StringBuilder sb = new StringBuilder();
           sb.append("========================= ");
           sb.append("购物时间:").append(new Date()).append(" ");
           int pos = -1;
           for (Merchandise m : buy) {
               pos++;
               if (m == null) {
                   continue;
              }
               sb.append(m.getCategory().name()).append(" ").append(m.getName()).append(" ")
                  .append(count[pos]).append(" ").append(m.getPurchasePrice() * count[pos]).append(" ");

          }
           sb.append("应付总额为:").append(calculateOriginCost()).append(" ");
           sb.append("=========================");
           return sb.toString();
      }

    }

    SuperMarket

    package com.geekbang.supermarket.interfaces;

    public interface SuperMarket {

       Merchandise[] getAllMerchandise();

       Merchandise[] getRandomMerchandiseOfCategory(Category category);

       void addEarnedMoney(double earnedMoney);

       void dailyReport();

    }

    com.geekbang.supermarket.impl

    AbsCustomer

    package com.geekbang.supermarket.impl;

    import com.geekbang.supermarket.interfaces.Category;
    import com.geekbang.supermarket.interfaces.Customer;
    import com.geekbang.supermarket.interfaces.ShoppingCart;

    import static com.geekbang.supermarket.util.ShoppingUtil.getRandomCategory;

    public abstract class AbsCustomer implements Customer {
       private Category shouldBuy;
       private String custId;
       private double moneySpent;
       private int guangLeft = 0;
       private int guangCount = 0;

       public static final int DEFAULT_GUANG_COUNT = 5;

       public AbsCustomer(String custId, Category shouldBuy, int guangCount) {
           this.shouldBuy = shouldBuy;
           this.guangCount = guangCount;
           this.custId = custId;
      }

       public int getGuangCount() {
           return guangCount;
      }

       public void setGuangCount(int guangCount) {
           this.guangCount = guangCount;
      }

       public AbsCustomer(String custId, Category shouldBuy) {
           this(custId, shouldBuy, DEFAULT_GUANG_COUNT);
      }

       @Override
       public String getCustId() {
           return custId;
      }

       @Override
       public void startShopping() {
           guangLeft = guangCount;
      }

       @Override
       public boolean wantToCheckout() {
           guangLeft--;
           return guangLeft <= 0;
      }

       @Override
       public double payFor(ShoppingCart shoppingCart, double totalCost) {
           // TODO 留给大家的思考题,买不起怎么办?
           moneySpent += totalCost;
           return totalCost;
      }

       public Category getShouldBuy() {
           return shouldBuy;
      }

       /**
        * 先看必须买的,没有必须买的就随便看看
        *
        * @return 想要购买的商品种类
        */
       @Override
       public Category chooseCategory() {
           // 有一次机会看需要买的东西
           if (guangLeft + 1 >= guangCount) {
               return shouldBuy;
          } else {
               return getRandomCategory();
          }
      }

       @Override
       public double getMoneySpent() {
           return moneySpent;
      }
    }

    cashcard

    package com.geekbang.supermarket.impl;

    import com.geekbang.supermarket.interfaces.Card;
    import com.geekbang.supermarket.interfaces.Customer;
    import com.geekbang.supermarket.interfaces.ShoppingCart;

    /**
    * 抵扣现金的卡
    */
    // TODO: 思考题:怎么使用这个类才好呢?
    public class CashCard implements Card {

       // 1:1抵扣现金的点数
       private double point;

       public CashCard(double point) {
           this.point = point;
      }

       @Override
       public double processCardDiscount(double totalCost, double totalCostAfterDiscount,
                                         Customer customer, ShoppingCart shoppingCart) {
           // 如果折扣下来剩下的钱比点数少,那么就抵扣掉需要付的剩下的钱
           if (totalCostAfterDiscount < point) {
               point -= totalCostAfterDiscount;
               return totalCostAfterDiscount;
          } else {
               // 否则就抵扣掉所有的点
               point = 0;
               return point;
          }
      }
    }

    simpleMerchandise

    package com.geekbang.supermarket.impl;

    import com.geekbang.supermarket.interfaces.Category;
    import com.geekbang.supermarket.interfaces.Merchandise;

    public class SimpleMerchandise implements Merchandise {

       private String name;
       private double soldPrice;
       private double purchasePrice;
       private int count;
       private Category category;

       public SimpleMerchandise(String name, double soldPrice, double purchasePrice, int count, Category category) {
           this.name = name;
           this.soldPrice = soldPrice;
           this.purchasePrice = purchasePrice;
           this.count = count;
           this.category = category;
      }

       @Override
       public String getName() {
           return name;
      }

       @Override
       public double getSoldPrice() {
           return soldPrice;
      }

       @Override
       public double getPurchasePrice() {
           return purchasePrice;
      }

       @Override
       public int buy(int count) {
           // TODO 思考题:卖超了怎么办?
           this.count -= count;
           return count;
      }

       @Override
       public void putBack(int count) {
           this.count += count;
      }

       @Override
       public Category getCategory() {
           return category;
      }

       @Override
       public int getCount() {
           return count;
      }

       public void setCount(int count) {
           this.count = count;
      }
    }

    SimpleShopman

    package com.geekbang.supermarket.impl;

    import com.geekbang.supermarket.interfaces.*;

    import static com.geekbang.supermarket.util.ShoppingUtil.output;

    public class SimpleShopman implements Shopman {

       private SuperMarket superMarket;

       public SimpleShopman(SuperMarket superMarket) {
           this.superMarket = superMarket;
      }

       private static final int MAX_BUY_DEFAULT = 9;

       @Override
       public void serveCustomer(Customer customer) {
           int maxTypeToBuy = MAX_BUY_DEFAULT;
           if (customer instanceof AbsCustomer) {
               maxTypeToBuy = ((AbsCustomer) customer).getGuangCount();
          }
           ShoppingCart shoppingCart = new ShoppingCart(maxTypeToBuy);
           customer.startShopping();

           while ((!customer.wantToCheckout()) && shoppingCart.canHold()) {
               Category category = customer.chooseCategory();
               // 简单的导购员,顾客说不想买就算了,不做推荐
               if (category == null) {
                   continue;
              }
               Merchandise[] toChoose = superMarket.getRandomMerchandiseOfCategory(category);
               // 简单的导购员,一个个推荐,不说从价格高到低推荐之类的小技巧。
               for (Merchandise m : toChoose) {
                   if (m == null) {
                       continue;
                  }
                   int buyCount = customer.buyMerchandise(m);
                   if (buyCount > 0) {
                       // 一个类别只买一个商品
                       shoppingCart.add(m, buyCount);
                       break;
                  }
              }
          }

           double originCost = shoppingCart.calculateOriginCost();
           double finalCost = originCost;

           double savedMoney = 0;
           if (customer instanceof HasCard) {
               Card card = ((HasCard) customer).getCard();
               savedMoney = card.processCardDiscount(originCost, finalCost, customer, shoppingCart);
               finalCost -= savedMoney;
          }

           double moneyEarned = customer.payFor(shoppingCart, finalCost);

           superMarket.addEarnedMoney(moneyEarned);

           output("顾客" + customer.getCustId() + "购物清单如下:");
           output(shoppingCart.toString());
           output("优惠金额为:" + savedMoney);
           output("实付金额为:" + moneyEarned);


           // >> TODO 思考题:上面的代码是否太过复杂了?如果有别的类型的shopmain,是否有代码可以重用?有的话应该怎么办?

      }


    }

    SimpleSuperMarket

    package com.geekbang.supermarket.impl;

    import com.geekbang.supermarket.interfaces.Category;
    import com.geekbang.supermarket.interfaces.Merchandise;
    import com.geekbang.supermarket.interfaces.SuperMarket;

    import static com.geekbang.supermarket.util.ShoppingUtil.output;

    public class SimpleSuperMarket implements SuperMarket {

       private String name = "无名";

       private Merchandise[] all;
       private int[] allCount;

       private double totalMoneyEarn;

       private int customerCount;

       public SimpleSuperMarket(Merchandise[] all) {
           this.all = all;
           allCount = new int[all.length];
           for (int i = 0; i < all.length; i++) {
               allCount[i] = all[i].getCount();
          }
      }

       @Override
       public Merchandise[] getAllMerchandise() {
           return all;
      }

       @Override
       public Merchandise[] getRandomMerchandiseOfCategory(Category category) {
           Merchandise[] ret = new Merchandise[5];
           int pos = 0;
           for (Merchandise m : all) {
               if (m.getCategory() == category && Math.random() > 0.5 && pos < ret.length - 1) {
                   ret[pos] = m;
                   pos++;
              }
          }
           return ret;
      }

       @Override
       public void addEarnedMoney(double moneyEarn) {
           customerCount++;
           this.totalMoneyEarn += moneyEarn;
      }

       @Override
       public void dailyReport() {
           output("营业额为:" + totalMoneyEarn);
           output("商品售出情况如下:");
           for (int i = 0; i < all.length; i++) {
               if (allCount[i] != all[i].getCount()) {
                   System.out.println(all[i].getCategory().name()
                       + " " + all[i].getName() + " " + (allCount[i] - all[i].getCount()));
              }
          }


      }

       public String getName() {
           return name;
      }

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


    }

    SuiYuanCustomer

    package com.geekbang.supermarket.impl;

    import com.geekbang.supermarket.interfaces.Category;
    import com.geekbang.supermarket.interfaces.Merchandise;

    public class SuiYuanCustomer extends AbsCustomer {

       private static final double MUST_BUY_CHANCE = 0.8;
       private static final double GUANG_BUY_CHANCE = 0.1;

       public SuiYuanCustomer(String custId, Category mustBuy) {
           super(custId, mustBuy, DEFAULT_GUANG_COUNT);
      }

       @Override
       public int buyMerchandise(Merchandise merchandise) {
           // 买一个商品的概率
           double chanceToBuy = merchandise.getCategory() == getShouldBuy() ?
               MUST_BUY_CHANCE : GUANG_BUY_CHANCE;

           // 缘分不到,那就返回 0
           if (chanceToBuy < Math.random()) {
               return 0;
          } else {
               // 否则就买1个或者多个,看缘分到哪儿
               return 1 + (int) (Math.random() * 3);
          }
      }

    }

    ThinkAndButCustomer

    package com.geekbang.supermarket.impl;

    import com.geekbang.supermarket.interfaces.Card;
    import com.geekbang.supermarket.interfaces.Category;
    import com.geekbang.supermarket.interfaces.HasCard;
    import com.geekbang.supermarket.interfaces.Merchandise;

    public class ThinkAndBuyCustomer extends AbsCustomer implements HasCard {

       private Card card = VIPCard.Level0;

       public ThinkAndBuyCustomer(String custId, Category shouldBuy) {
           super(custId, shouldBuy, DEFAULT_GUANG_COUNT);
      }

       @Override
       public int buyMerchandise(Merchandise merchandise) {

           Category category = merchandise.getCategory();
           // 需要买的就买一个
           if (category == getShouldBuy()) {
               return 1;
          }

           double soldPrice = merchandise.getSoldPrice();

           double avgPrice = (category.getHigherPrice() + category.getLowerPrice()) / 2;
           if (soldPrice < avgPrice) {
               return 1;
          } else {
               return 0;
          }
      }

       public void setCard(Card card) {
           this.card = card;
      }

       @Override
       public Card getCard() {
           return card;
      }
    }

    VIPCard

    package com.geekbang.supermarket.impl;

    import com.geekbang.supermarket.interfaces.Card;
    import com.geekbang.supermarket.interfaces.Customer;
    import com.geekbang.supermarket.interfaces.ShoppingCart;

    public enum VIPCard implements Card {
       Level0(1),
       Level1(0.99),
       Level2(0.95),
       Level3(0.9),
       Level4(0.85),
       Level5(0.8);

       private double discount;

       VIPCard(double discount) {
           this.discount = discount;
      }

       @Override
       public double processCardDiscount(double totalCost, double totalCostAfterDiscount,
                                         Customer customer, ShoppingCart shoppingCart) {
           return totalCostAfterDiscount * (1 - discount);
      }
    }

     

    梦的远方,温暖为向,所到之处,遍地阳光!
  • 相关阅读:
    slurm.conf系统初始配置
    MySQL数据库服务器(YUM)安装
    Slurm任务调度系统部署和测试(源码)(1)
    并行管理工具——pdsh
    Munge服务部署和测试
    NTP服务部署和测试
    LDAP-openldap服务部署和测试(YUM安装)
    KVM虚拟机管理——虚拟机创建和操作系统安装
    KVM虚拟机管理——虚拟机克隆
    KVM虚拟化环境准备
  • 原文地址:https://www.cnblogs.com/blamwq/p/12120428.html
Copyright © 2011-2022 走看看