JAVASE

程序注释

​ 任何一套程序代码里面实际上都会由大量的程序逻辑所组成,但是如果要想对一套代码进行长期的维护,就需要编写大量的注释,对一些程序的代码功能要进行详细的解释,这样不仅为自己铺平道路,实际上也为后来接手的工程师铺平道路。

关于注释的笑话:有一位程序员到一家新的公司进行项目开发,突然有一天老板说,某一个功能执行的速度实在是太慢了,让这位程序员修改一下,后来这个程序员找到了相关源代码,里面写上了一个注释“后面的兄弟,悠着点,我在这里吗让代码延迟了3秒,别一下子改的太快了,给后面的兄弟留点发挥空间”,于是这位工程师根据前辈的注释进行了修改,将原始的延迟3秒,修改为了延迟2.5秒,速度变快了,老板给了奖金。

​ 在Java程序里面针对于代码的注释一共提供了三种注释形式:

  • ​ 单行注释:“// 注释内容”;(考虑到开发工具的代码格式化问题)

  • ​ 多行注释:“/*… 注释内容 … */“;

  • ​ 文档注释:“/** … 文档注释的特定语法标记进行注释的编写 …… */”,这种注释往往可以结合开发工具使用

1
2
3
4
5
6
7
8
public class YootkDemo{ // 【单行注释】定义程序的执行主类
public static void main(String args[]){// 【单行注释】程序的执行起点,主方法
/*【多行注释】
以下的程序代码是在屏幕上进行一些提示信息的输出,如果有需要则可以再里面进行多行的定义
*/
System.out.println("Hello world!");
}
}

​ 既然所有的注释文字不会自己进行代码的编译处理,所以在实际项目开发之中可以将一些暂时不需要的代码通过注释的形式让其失效,这种形式要比直接删除代码更高效。

1
2
3
4
5
6
7
8
9
public class YootkDemo{ // 【单行注释】定义程序的执行主类
public static void main(String args[]){// 【单行注释】程序的执行起点,主方法
/*【多行注释】
以下的程序代码是在屏幕上进行一些提示信息的输出,如果有需要则可以再里面进行多行的定义
*/
System.out.println("Hello world!");
// 【代码失效】 System.out.println("江湖上称我为");
}
}

在以后进行项目开发的时候,一些暂时不需要的代码就可以利用注释进行关闭。

标识符

  在任何一个程序里面都一定会有大量的名称进行一些特定结构的声明,例如:在Java程序里面一直强调,每一个程序都是一个类,那么所有的类就一定要有类的名称,这就是属于一个标识符,所有的程序编译器都是依据这个名称来进行代码结构管理的,既然要进行管理,对于名称就有它的命名要求。

在java之中所有的标识符由字母、数字、下划线(_)以及“$”所组成的,其中不能使用数字开头,不能够使用java关键字(保留字)进行标识符定义。
顺便说一下:正常的标识符里面一般都要求有具体的严格意义,例如:你在程序里面定义了a、b、c一系列的标识符,那么这些意义不明确,所以代码
阅读起来是非常困难的。另外对于标识符定义中的“$”也不要去直接使用,因为其有特殊的含义,所以一般来讲标识符的组成就是字母、下划线、数字
所组成的,建议使用字母开头。

yootk_name,YootkDemo,teacherLee,num_110(正确形式)

110_No.1(使用数字开头、并且使用了“.”作为了标识符的组成)
abc#hello(使用了非法的“#”符号作为了标识符)
class(使用了程序中的关键字(保留字),那么这种标识符也是错误的。)

  任何的编程语言里面都会提供有大量的关键字,这些关键字往往都具有特殊的含义,java中的关键字会随着每次版本的更新而有所扩充。

很多的语言里面都有许多相同的关键字(java、C、++是一个系列的):for,if,else,swich,while、……;
java有两个未使用到的关键字:goto(代码调试的万恶之手)、const(定义常量,被final所取代);
有三个特殊含义的标记(严格来讲不属于关键字):null、true、false;
JDK1.4之后更新了assert关键字,用于断言操作;
JDK1.5之后扩充了enum关键字,用于进行枚举定义;
JDK1.10之后扩充var关键字,用于进行匹配类型变量的定义;
JDK1.13之后扩充yield关键字,进行局部返回。

除了以上的标识符定义要求之外,实际上java也考虑到中国的地位,也推出了一些比较神奇的做法,可以直接使用中文进行标识符的定义。

范例:使用中文标识符

    public class 优拓公开课{ // 【单行注释】定义程序的执行主类
    public static void main(String args[]){// 【单行注释】程序的执行起点,主方法
        /*【多行注释】
            以下的程序代码是在屏幕上进行一些提示信息的输出,如果有需要则可以再里面进行多行的定义    
        */
        int 年龄 = 18;//中文定义
        System.out.println("Hello world!"); 
        // 【代码失效】 System.out.println("江湖上称我为"); 
    }
}

​ 这种定义的形式可以作为娱乐,但是正常的开发者一般都不会采用这样的形式来进行标识符的定义,还应该使用传统的字母、数字之类的进行定义,除了标识符的组成要求之外,在Java里面或者是在实际的工作之中还会有一些命名规范的出现,命名规范都要求遵循标识符的组成原则,但是对于大小写的定义是有描述的,例如:类名称每个单词的首字母大写(例如:YootkDemo),这些具体的描述可以根据不同的公司来动态调整。

数据类型

具体内容

任何的程序设计语言本身就属于一场数字的游戏,如果说我们的人生就是一部自我完善的坚史,那么编程语言既然是一种现实物理和数学的抽象,其背后就是数字的一场游戏(计算机的组成的核心本质只有数字:“0”、“1”),那么既然要进行数字的操作,则需要进行数据的存储,所以任何的编程语言里面都会设计有一系列的数据类型,利用不同的数据类型保存相应的类型

例如:如果要是描述年龄,那么肯定要使用整数。如果要进行折扣处理的话,往往就希望这个小数点越小越好,所以就需要浮点型。所以任何一门完善的编程语言其数据类型的支持程序都是异常丰富的。
  在java程序的内部对于数据类型实际上分为两大类型:

【分类】基本数据类型:所有的数据操作都是采用值传递,相当于把数据给了对方一个副本信息,副本信息的修改不影响原始的数据内容,这些基本数据类型也是构成程序开发的基本环节;

|-【子分类】整型:byte、short、int、long;        -->默认值:0
|-【子分类】浮点型(有小数点=小数):float、double;    -->默认值:0.0
|-【子分类】字符型:char;                -->默认值:'\u0000'(十六进制)
|-【子分类】布尔型:boolean.                -->默认值:false(特殊意义的关键字)

【分类】引用数据类型:是进行内存的数据操作,给的内存使用权。是所有初学者最难理解的部分;

|-有三种引用数据类型:数组、类、接口。            -->默认值:null(特殊意义的关键字)

提示:整个的Java编程语言之中由于对C、C++进行了结构上的优化(Java是基于C++开发出来的),在整个的C、C++里面最让人头疼的部分就是指针,而java为了解决这个问题,取消了指针的定义,而使用了更加简单的引用数据类型来进行代替,在后面进行面向对象讲解开始的时候将对引用数据类型做出全面的分析

  在java开发过程之中,对于基本数据类型(最为核心的数据类型)默认一共提供有八种类型,其中有7种类型是由明确的数据存储范围(计算机里面所有的数据内容都是通过二进制的形式保存的,所有的数据都有一个保存的上限&下限)

-byte: 描述的是字节,在进行网络数据传输一定是字节数据处理,也会用在编码转换上;(1字节)
-int:描述的是整型,例如:定义年龄;(4字节)
-long:描述的是长整型(范围比int广),用在进行文件大小描述、日期时间的描述上;(8个字节)
-double:描述小数,例如:要进行工资的定义,则肯定是小数;(8个字节)
-char:主要是进行中文处理;(2个字节)
-*boolean*:进行逻辑表述。

变量与常量

变量与常量是在整个程序计算过程之中主要使用的两个数据的存储形式,其中所有给定的不可能修改的内容我们将其称为常量,而所有可以修改的内容就将其称为变量。

范例:观察变量

public class DongJun{ 
public static void main(String DongJun[]){
    //10是一个数字,既然已经定义好了10,那么就意味着这个内容无法修改了
    System.out.println(10); //常量
}
}

程序执行结果:10

在上学的时候学校经常会用一种方式去惩戒哪些所谓的“调皮的学生”,就是将你的行为和处分决定记录在你的档案里面,这些内容将持续陪伴你,并且不会变更,那么就可以将这些记录定义为你个人的常量
变量顾名思义就是内容可以改变的标记,所有的变量都一定要有其对应的数据类型,例如:int,double都属于数据类型,每一种变量可以根据其定义的数据类型进行内容的修改。

如果要想使用变量则必须进行定义,而变量的定义语法形式为:“数据类型 变量名称 = 默认值”,而这个变量名称实际上就是之前讲解的标识符的组成,相当于你自己定义的有意义的名称。

范例:定义变量

public class DongJun{ 
public static void main(String DongJun[]){
    //所有程序语言最后一定要使用;作为结尾
    int age = 10;//定义一个整型变量,并且设置了默认值
    System.out.println(age); //输出变量内容
    age = 19; //赋值
    System.out.println(age); //输出变量内容
}
}    

程序执行结果: 18
19

按照正常的设计来讲每一种数据类型即便不设置默认值,那么也应该使用其对应数据类型的默认值进行定义,但是如果你的代码写成如下的形式,则执行的时候一定是错误的

public class DongJun{ 
    public static void main(String DongJun[]){
        int age ;//如果现在没有定义具体的内容,则应该使用默认值“0”来表示
        System.out.println(age);
    }
}

D:\yootk>javac DongJun.java
DongJun.java:4: 错误: 可能尚未初始化变量age
System.out.println(age);

本次主要是观察变量声明和赋值在不同的JDk版本里面所带来的流程上的区别。
范例:在JDK1.4及以前的版本

要求在主方法中定义变量的同事一定要为其设置默认值,如果不设置就出错;

范例:在JDK1.5及以及以后

在主方法中定义变量的时候可以不设置默认值,但是在其使用之前一定要进行默认值设置,否则会出现编译错误

如果把常量比喻为不同的咖啡:美式、拿铁、卡布奇诺,这些调制好了的东西一般是不会发生改变的,而如果是变量那么就好比是你的咖啡杯,咖啡杯可以装不同咖啡,但是当你需要更换咖啡的时候,那么就意味着你原始的咖啡就没了,而盛的咖啡就是新的。

整型

在现实的生活里面数学上一般都会存在有整数的概念,整数实际上描述就是没有小数点的内容,是一个完整的十进制的数值。
例如:如果要想表示一个人的年龄肯定要使用整数,如果要想去描述住房楼层肯定也使用整数,在Java程序里面,对于整数的数据类型一共有四种支持:Byte、short、int、long。
  在给定的这四种整型数据类型里面,最为常用的数据类型就是Int型,在java程序之中任何的一个整型数字的常量默认对应的类型全部都是整型。
定义int变量

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        //数据类型 变量名称 = 常量、整数常量的默认类型为 int
        int number = 10; //定义一个整型变量
        // int变量-=  int变量数值 + 20 常量(int类型)
        number = number + 20; // 进行变量的加法计算
        System.out.println(number);
    }
}    

程序执行结果:30

虽然int 可以解决大部分的整型的数据操作问题,但是从另外的角度来讲,对于当前程序开发来说,int本身是由其长度范围(-2147483648-2147483647),那么如果说超过了这个计算范围,则就有可能出错。

public class DongJun{ 
static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
public static void main(String DongJun[]){
    //数据类型 变量名称 = 常量、整数常量的默认类型为 int
    int max = 2147483647; //定义一个整型变量
    // int变量-=  int变量数值 + 20 常量(int类型)
    max = max + 1; // 进行变量的加法计算
    System.out.println(max);
}
}

程序执行结果-2147483648

这里面就存在了计算机之中的基本概念:二进制的数据计算问题了。在程序之中所有的数据都是被二进制的操作进行管理的,但是由于Java编程语言属于高级编程语言,所以对于一些底层的细节就由编程语言自己来处理。

专业描述:Java之中int数据类型一共有32位,第一位属于符号位,其余的位数属于数据位。每一次进行所谓的加或减的时候实际上都是在底层进行了二进制数据计算,当已经最大值的似乎还“011111”,如果再进行加1的处理,符号位就会发生改变,所以就变为了最小值。

  对于以上的问题在程序开发之中可以理解为数据的溢出,数据溢出采用的是一种循环的模式进行处理的。

如果要想解决这种数据溢出的问题,那么最佳的做法就是扩大使用的数据范围,比int范围更大的数据范围就是long,所有的编程语言里面对于数据范围的扩大都使用自动的扩大的形式,例如:如果现在是一个int型变量和一个long型变量进行加法操作,那么必定要先进行数据类型的统一,而这种统一的操作过程就是将int类型自动转为long的类型。从而形成最终的两个long型变量的计算操作。
范例:通过long数据类型解决int的溢出问题

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        //数据类型 变量名称 = 常量、整数常量的默认类型为 int
        int max = 2147483647; //定义一个整型变量
        // int变量-=  int变量数值 + 20 常量(int类型)
        System.out.println(max+1L);
    }
}

程序执行结果2147483648

由于默认的整数对应的类型为int,所以如果要想将其变为long的常量则可以使用“整数L”、“整数l”(“小写L”比较坑)因为其长的和1很相似(如果你没有受过一定的训练是看不出的)
结论:如果要想解决数据溢出问题,肯定要使用更大的数据类型来进行处理。

  这个时候就会出现一个新的概念:数据类型的转换,不同的数据类型之间是可以进行转换的,但是在进行转换的处理过程之中一般都会使用如下的两个转换原则。

自动类型转换:保存数据范围小的数据类型如果遇见了保存范围数据大的数据类型,则范围小的数据类型自动转换为范围大的数据类型后再进行计算,之前的程序就属于这种自动转换。

范例:数据类型的自动转换

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        //数据类型 变量名称 = 常量、整数常量的默认类型为 int
        int num_a = 10 ;
        long num_b = 20;
        //num_a这个int变量由于其数据类型的位数不足,所以将自己转换为long类型后在于num_b进行加法计算
        lonmg result = num_a + num_b;
        System.out.println(result);
    }
}

强制类型转换:将保存数据范围大的数据类型强制的变为保存数据范围小的数据类型,这种转换由于需要缩小数据类型的保存位数,所以就有可能产生数据溢出问(数据出错)

范例:数据类型的强制转换

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        //数据类型 变量名称 = 常量、整数常量的默认类型为 int
        //此时必须强制性的将整型常量转为long类型才可以正常保存在long变量之中
        long num = 2147483677L; //该类型已经超过了int的最大内容
        System.out.println(num);
        System.out.println((int)num);
    }
}

2147483677
-2147483619

*所以这种数据范围的强制转型所带来的最为严重的问题就是有可能会有数据的溢出情况出现,所以如果你非要进行强制性类型转型,那么一定要注意其最终的目标数据类型是否可以包含下当前的数据内容。
  通过以上的分析实际上就可以得到一个最为重要的结论:在进行不同数据类型操作的过程之中,一定会首发发送自动的扩大类型的转型操作,而后再进行计算,但是一般不建议使用强制的类型转换,因为有可能会有数据溢出的问题。

既然有了整型的概念,就必须重点分析一下byte数据类型问题

回顾:针对于不同数据类型的使用
    byte:主要用于网络传输、二进制数据处理、编码转换(在讲解IO和网络编程会使用到)
    int:描述大部分的整型数值,以后见到整型的需求首先考虑就是int型变量或常量;
    long:主要描述文件大小或者是日期时间的数字(以后讲解到类库的时候会进行说明)

byte描述的是一个字节,java程序开发之中的每一个字节所能描述的数据范围:”-128-127”,就需要注意其不能够存储更大的数据信息。

范例:定义byte变量

public class DongJun{ 
static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
public static void main(String DongJun[]){
    byte data = 10 ; //定义一个byte变量
    System.out.println(data);
}
}

10

以上的程序实现了最为基础的byte变量的定义以及内容的输出,但是在整个的程序执行过程之中会有一个小小的问题出现了:按照之前的概念来讲,此时的数字10应该是一个int型的常量,那么按照以上操作来讲应该是int型的常量赋值给了byte型的变量,出现了一个与之前概念不匹配的应用环境,之所以没有这种强制的转换需求,主要的原因在于:Java针对于符合byte范围内,那么就必须进行强制转换处理。

范例:超过byte范围强制处理
public class DongJun{
static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
public static void main(String DongJun[]){
byte data = (byte)250 ; //定义一个byte变量
System.out.println(data);
}
}

-6

此时由于设置的整型内容超过了byte范围,所以一旦强制性转换之后就产生了数据的溢出问题;

浮点型

浮点型最大的特点就是在数字里面包含有小数点,在Java程序里面针对于浮点型数据类型提供了两个关键字:

- 单精度浮点数据类型:float,包含32位的数据长度
- 双精度浮点数据类型:double,包含64位的数据长度
在Java里面,任何的一个小数其默认的数据类型均为double(double可以保存全宇宙里面最大的一个数值),double是整个是所有数据类型之中可以保存数据内容最大的一种类型。

范例:定义double变量

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        //double 变量 = 常量 (double变量)
        double num_a  = 99.89 ; //定义double变量
        int num_b = 199; 
        //double变量(num_a) + double变量(num_b,int自动转为double) = double结果
        double result = num_a + num_b ; 
        System.out.println(result);
    }
}

>298.89

  java之所以没有使用float作为小数的默认类型,主要是考虑到float计算本身存在的二进制位的操作问题(会产生精度问题),这个问题是整个计算机编程语言行业之中最大的问题(娘胎带的问题了),所以在java里面如果要想定义float变量,就必须将小数的常量进行强制的类型转换才可以正常进行。

范例:定义float型变量

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        float num_a  = 10.0F ; //将double常量强制转换为float变量
        float num_b  = (float) 0.4; //将double常量强制转换为float变量
        System.out.println(num_a/num_b);


    }
}

> 25.0

范例:观察float可能存在的问题

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        float num_a  = 9.9F ; //将double常量强制转换为float变量
        float num_b  = (float) 0.3; //将double常量强制转换为float变量
        System.out.println(num_a/num_b);


    }
}

32.999996(会出现许多小数)
  float数据类型本身是有问题的,而正因为这些问题的存在,所以不建议使用float这种数据类型进行浮点数定义,最好使用double。

范例:通过double可以解决float的问题

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        double num_a  = 9.9 ; //将double常量强制转换为float变量
        double num_b  =  0.3; //将double常量强制转换为float变量
        System.out.println(num_a/num_b);


    }
}

33.0

  在以后的项目开发过程之中肯定要首选double作为小数的数据类型。

在项目的开发之中整型和浮点型之间最大的区别就是小数点,也就是所有的整型数据内容是不会保留小数位的,那么如果说现在计算的数据本身会产生小数位,则如果没有使用浮点型而使用整型,对应的小数位会全部丢弃。(如果要想准确,那么就必须采用小数来进行计算,需要将其中的一个计算的内容变成double)

范例:解决小数点的保留问题

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        int num_a = 9 ;
        int num_b = 2 ; 
        System.out.println(num_a/(double)num_b);

    }
}

4.5

如果在计算之中某一个类型变为了double,则其他的类型都要变为double(double范围是最广的),这个时候当前的计算结果一定是double类型。

通过以上的分析,应该就已经非常清楚了这些数值型的数据类型的自动转换操作过程:byte>short>int>long>float>double(保存范围小的自动进行转换),而在进行强制类型转换的时候,如果浮点型强制变为了整型,那么就会丢掉小数点。

在未来选择数值型数字类型的时候,整型就使用int,浮点型(小数)就使用double

字符型

  在java程序里面,依然提供有传统编程语言使用的字符的概念,字符是使用“’”声明的一个内容,字符提供有char关键字来进行类型的定义。

范例:字符的定义

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        char c=  'y';//字符需要使用单引号进行声明
        System.out.println(c);

    }
}

y

在使用字符进行初始化内容赋值的时候后,一定只能够设置一位内容,如果设置了多位,语法一定会出错。 

  在程序之中字符(char)可以和整型(int)直接进行转化处理,而字符转换为整型之后得到的数值就属于字符的编码。

  那么既然所有的字符在JVM里面都有相应的编码存在,这样一来就必须非常清楚几个常见的字符范围的定义:

小写字符范围('a'~'z'):97~122;
大写字符范围('A'~'Z'):65~90;
数字字符范围('0'~'9'):48~57

于是这个时候有人发现一个问题:大写字符和小写字母之间的编码的数值内容差32个,所以理论上修改数值就可以进行大小写的控制,下面市县一个小写字母转大写字母的操作。

范例:小写字母转为大写字母

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        char c=  'a'-32;//字符需要使用单引号进行声明
        System.out.println(c);

    }
}

A

通过以上的分析实际上是许多的读者就应该发现一个比较熟悉的昌吉了,这个场景的内容就是常规的编程语言里面所出现ASCII码的内容(在整个计算机内部核心的组成就是”0”,”1”),但是需要描述的内容太多了,所以就需要对这些数值进行合理的安排,就可以基于不同的内容实现相应字符的显示

需要提醒读者的是,在使用java开发的时候后,所采用的并不是这种ASCII码,JAVA在其设计的时候已经充分的考虑了当前的开发市场(C、C++为主时代)所有的开发者都已经习惯于这样的编码顺序,那么在进行java编码的设计的时候就将传统的ASCII码包含在当前语言设计的编码当中,开发了属于JAVA自己的十六进制编码,该编码的名称为“UNICODE”。UNICODE是一个非常强大的编码,可以描述出世界上任意的文字,包括中文、日文等。

范例:通过char保存中文

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        char c=  '俊';//传统的ASCII码是不包含中文定义的
        int num = c;
        System.out.println(num);

    }
}

20426(这个数值已经远远超过了byte可能描述的数据范围)

  UNICODE描述了一个更广阔的编码范围,其中也很好的支持有传统的AsCII编码,让所有的开发者在使用上不会产生任何的不适应感。由于字符可以保存中文,所以在日后进行网络数据传输的时候,如果要进行中文数据的处理,建议使用的就是char来进行操作。

布尔型

  布尔型是一种描述处理结果的逻辑内容,对于计算机的世界来讲除了真就是假,没有中间的过渡环节,布尔在java编程语言里面使用boolean关键字来进行定义,而布尔的取值只有两个内容:True、False(这两个在java中都属于有特殊含义的关键字)

如果要想使用布尔类型进行程序的开发,往往都需要结合一些分支语句的结果进行使用

范例:使用布尔型

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        boolean flag = true;
        if(flag){
            System.out.println("1");
        }
    }
}

**  如果此时设置flag的内容为false,那么对于当前的if判断就不会成立。既然已经谈到布尔数据类型就必须对一个语言的区别进行一些描述。**

  如果你使用的是C、C++编程开发,在这样的编程语言里面基本上强调都是通过数字0来描述FALSE,而通过一个非0的数字来描述TRUE,通过这样的数值来描述布尔值,但是在JAVA之中并不存在于这样的概念。

String 字符串

  在任何一门语言里面实际上字符串都属于一种比较特殊的类型,而JAVA之中字符串也属于非常特殊的一种数据形式,它不是基本数据类型,而它属于一种引用数据类型,因为字符串的类型要使用“String”声明,而在JAVA编写程序代码的过程之中已经明确强调了:首字母大写的一定是类,所以String是一个系统类(这个系统类的设计是非常繁琐的,后面会有专门的内容进行全面分析),本次先来观察一下String的基本使用

  在程序里面如果要想描述单个字符肯定要使用char类型(通过“’”声明),但是如果要想描述一组的字符,就可以通过字符串的形式来处理。

范例:定义字符串

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        String message = "董俊";
        System.out.println(message);

    }
}

董俊

**  需要注意的是,每一个字符串实际上都可以进行内容的连接,而内容的连接,可以通过“+”来实现(不是数字的加法而表述的是一个连接操作)**

范例:字符串连接操作
public class DongJun{
static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
public static void main(String DongJun[]){
String message = “姓名:”;
message = “我的” + message ;
System.out.println(message+”董俊”);

    }
}

  既然在字符串之中“+”属于连接的操作形式,所以这个时候就会存在有另外一个问题:如果现在直接与其他基本数据类型进行连接又会如何呢?

范例:观察基本数据类型与字符串的连接

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        String prompt = "数据输出";
        System.out.println(prompt + 1);
        System.out.println(prompt + 1.1);
        System.out.println(prompt + 'Y');
        System.out.println(prompt + true);


    }
}

数据输出1
数据输出1.1
数据输出Y(字符并没有变为数字,而是直接使用了原始的字符内容)
数据输出true

以上仅仅是连接了一些基本数据型常量,那么如果说现在连接的是一些基本的计算表达式,那么请继续观察程序问题。

范例:观察计算表达式问题

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        double num_a = 9.5 ;
        int num_b  = 3 ;
        System.out.println("数学计算:"+num_a + num_b);
    }
}

数学计算:9.53(字符串连接)

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        double num_a = 9.5 ;
        int num_b  = 3 ;
        System.out.println("数学计算:"+(num_a + num_b));
    }
}

数学计算:12.5(先数学计算再连接)

**  之所以此时要强调这种问题的关键在于,在进行字符串处理的时候“+”和数学计算的“+”会有那么一些麻烦的表述,当java任何的数据类型与字符串进行连接的似乎还,所有的数据类型会首先变为字符串,按照此时的代码,首先执行的是“字符串+double变量”,自动转为String的字符串,而后这个字符串再通过“+”连接一个整型,这个时候的整型也会自动转为字符串,所以最终的计算就称为了一个字符串的连接操作,而加上了括号之后表示要先计算括号内部的数据加法(double类型),最后再与字符串进行连接操作(double自动转为了String)但是这些操作仅仅是发生在包含有“+”的概念上,如果使用的是其他的运算,例如使用的是“-”,那么该程序在编译的时候就会出错**

另外需要提醒大家的是,在进行字符串定义的时候本身如果包含有一些特殊的内容肯定是无法直接定义的,所以在这样的情况下要想描述一些特殊标记的符号就要使用转义字符,常见的转义字符为:双引号("、“\"”)、单引号('、“\'”)、换行符(“\n”)、制表符(“\t”)。

范例:观察转义字符

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        String message = "董俊\"\n\\\t我的填";
        System.out.println(message);
    }
}

这些转义字符也就在基础学习的过程之中有些作用,主要可以让内容的输出更加好看一些,但是如果在实际上的开发里面用处不是特别大

var关键字

Java 本身属于一门静态变成语言,在进行各个变量定义的时候就必须明确的声明变量的类型以及变量的具体内容(JDK1.5之后的版本要求是在使用之前复制),但是随着当今时代编程语言的技术发展,对于编程语言的要求也开始变得更多,所以这个时候很多的语言就退出了一个所谓的推断式变量定义,后来java在JDK1.10版本之中正式引入了此机制,所以提供了一个新的var关键字,这个关键字主要用于进行变量的定义,并且会根据所赋予的内容进行自动类型的配置。

范例:观察var关键字的使用

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        var num_a = 10.2 ;//将自动推断num_a类型为double
        var num_b = 3 ;//将自动推断num_b类型为int
        System.out.println(num_a - num_b);

    }
}

7.199999999999999(这种精度问题可以忽略)

public class DongJun{ 
static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
public static void main(String DongJun[]){
    var num_a = 10.2 ;//将自动推断num_a类型为double
    var num_b = 3 ;//将自动推断num_b类型为int
    System.out.println(((Object)num_b).getClass());//class java.lang.Integer
    System.out.println(((Object)num_a).getClass());//class java.lang.Double

}
}

**  在使用var关键字的时候除了可以为其赋值为基本数据类型之外,也可以设置字符串变量。**

范例:定义字符串变量

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        var message  = "董俊";
        System.out.println(message);

    }
}

董俊

**  于是这个时候就有人提出疑问了,按照现在的做法,感觉所有的变量都使用var定义实际上减少了我们对于关键字的记忆需求,为什么你又在这边强调不要去使用它呢?**

个人总结两个缺点:
    缺点一:像传统C、C++、Java这样编程语言对于数据类型都是有非常严格的要求,所以其对应的数据类型如果写的非常明确,那么就适合于程序的编写与调试,而如果使用var直接定义,那么类型不明确,于是世界上有一种变量的声明格式采用的是加入数据类型的模式完成例如:“var double_num_a = 10.2;”

    缺点二:其他语言的var是真正的动态类型(随时可以改变变量所保存的数类型的),而Java之中只是提供了一个var样子而已(一旦定义了变量,并且已经推断出了类型之后,那么该变量所保存的类型不允许改变)。

范例:错误的var操作

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        var num = 10.2;
        num = "www.yootk.com";


​ }
​ }

DongJun.java:5: 错误: 不兼容的类型: String无法转换为double
num = “www.yootk.com";
^
1 个错误
错误: 编译失败

综合以上的结论来讲,var关键字这种所谓的数据类型推断于实际的开发意义确实不是很大,这种操作尽量慎用

运算符

编程语言的本质是在于数学的计算(包括整个计算机的组成都是依据数学公式“冯诺依曼”),如果我们现在的程序开发使用的还是低级语言(汇编语言),那么所有的开发者就必须进行大量的细节处理,计算机的基本组成为二进制的数据,所以对于正数、负数、小数都需要进行各种二进制的计算转换,才可以通过计算机进行处理,但是如果所有的开发代码都还保持着这些低级语言的开发环境,那么对于技术的发展是非常不利的。

放低思维:在国内的互联网的历史上,百度肯定是作为一家搜索引擎的公司出现的,他自己有自己的开发技术,但是在早期的互联网时代之中,实际上为了便于上网出现了所谓的导航网站(早期的Yahoo)。
在国内的“hao123.com”,本身没有任何的技术难度,所以在这样的情况下,许多的初级网民就觉得非常好用,于是最终2000W卖给了百度.

*  如果所有的程序中的数学计算都要求每一位开发者进行所有底层的处理转换,那么计算机的发展肯定无法前进,那么作为高级编程语言(C、C++、JAVA、Python等),就必须读这些数学计算进行一系列的简化处理,所以才提出了所谓的运算符的概念,通过各种运算符以及编译操作过程就可以简化所有的计算处理。*

通过之前的学习实际上以及接触了两类运算符:
    |-赋值运算符:变量 = 内容(数据)、 变量 = 其他变量;
    |-数学运算符:+、-、*、/;
而除了以上可以见到的运算符之外,在Java程序之中依然还包括有许多的运算符,那么这些运算符基本的使用过程实际上和正常生活的数学逻辑是非常贴近的。

**  重要的运算符:四则运算、逻辑运算(大小关系)、三目运算、自增或自减运算,除了这些基本的运算符之外,实际上所有的运算符都有其运算优先级(先乘除后加减)**

高手的编程

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        int a = 10;
        int b = 20;
        int result = a++ - b++ * a - b-- /  ++b * ++a;
        System.out.println(result);

    }
}

-222(不要问为什么)

在你以后的开发生涯之中,如果你真的写出了这样代码,接手你代码的后续的开发者一定会跑路。

随着开发产业的不断发展,那么所谓的优秀的代码大部分都会有一种固定的特征:“全部编写简单按程序”,所有的代码可以像“1+1= 2”那样简单。

数学运算符

数学运算符是整个运算符之中最接近于原生生活的一种运算符,利用数学运算符可以方便的实现四则运算(加、减、乘、除、模),除了标配的运算符之外还提供有简化运算符。

模(MOD):在实际的项目开发过程里面,求模的意义可以实现数的批量控制,例如:每20个人站为一组

范例:通过求模的方式进行批量处理

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        int currentNumber  = 20 ; //定义变量
        int result = currentNumber % 20; // 如果先currentNuumber不是20,则模的结果一定不是0
        System.out.println("运算结果:"+result);

    }
}

运算结果: 0

对于求模的操作可能比较接近于当前基础环境的就只有一个常用的功能了:判断奇偶数(奇数模2为1,偶数模2为0)

实现奇偶数判断

public class DongJun{
static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
public static void main(String DongJun[]){
// 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
//Java中类的定义规则:每一个单词的首字母必须大写
int number = 3; // 定义变量
int result = number % 2 ;
System.out.println(“运算结果:”+result);
}
}

运算结果:1(现在判断的数字是一个奇数)

范例:简化运算符

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        int numberA =  33; // 定义变量
        int numberB =  33; // 定义变量
        int numberC =  33; // 定义变量
        int numberD =  33; // 定义变量
        int numberE =  33; // 定义变量
        numberA += 5;
        numberB -= 5;
        numberC *= 5;
        numberD /= 5;
        numberE %= 5;
        System.out.println("运算结果A:"+numberA);
        System.out.println("运算结果B:"+numberB);
        System.out.println("运算结果C:"+numberC);
        System.out.println("运算结果D:"+numberD);
        System.out.println("运算结果E:"+numberE);
    }
}

运算结果A:38
运算结果B:28
运算结果C:165
运算结果D:6
运算结果E:3

自增与自减运算符

在Java运算符里面针对于数学运算提供有“++”(自增运算,每一次调用内容都会“+1”处理)、“--”(自减运算,每一次调用内容都会“-1”处理),那么首先先来观察一下这两个运算符的基本使用。

范例:使用自增

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        int num = 10 ; 
        System.out.println("原始num变量内容:" + num);
        num++;//num+ = 1,但是性能要更高
        System.out.println("自增后num变量内容:" + num);
    }
}

原始num变量内容:10
自增后num变量内容:11

**  当执行了自增操作之后,原始内容会增加1**
以上见到的自增是我们在实际开发中最为推荐的操作方法,但是对于当前自增或者是自减运算又会根据位置的不同而有所不同,主要是发生在执行顺序上。

自增
"变量 ++":先计算后累加
"== 变量":先自增再计算
自减
"变量 --":先计算后自减
"-- 变量":先自减再计算

public class DongJun{
static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
public static void main(String DongJun[]){
// 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
//Java中类的定义规则:每一个单词的首字母必须大写
int numA = 10;
int numB = 5;
int result = numA + numB++;
System.out.println(“计算结果:” + result);
System.out.println(“numA=” + numA + “、numB=”+ numB);
}
}

计算结果:15
numA=10、numB=6

以上就实现了自增和自减

关系运算符

在程序设计之中对于数据的关系基本上就是:>, <, >=, <=, (不等于)!=, (等于)==
这些关系运算符可以直接应用在数值的描述上(字符本身也是可以与整数进行自动转换,所以字符上也可以使用。)

范例:比较两个数字的大小关系

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        int zsAge =  10 ;
        int lsAge =  20 ;
        boolean result = zsAge > lsAge;
        System.out.println(result);
    }
}

False

所有的关系运算符计算完成之后的数据类型是布尔类型(它的取值范围(True、False))

范例:实现浮点型数据比较

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        int zsAge =  10 ;
        int lsAge =  20 ;
        boolean result = zsAge > lsAge;
        System.out.println(result);
    }
}

true

**  直接利用数值的比较是在进行关系运算符处理过程之中最为常见的数据类型,但是千万不要忘记了,由于java程序本身使用了十六进制的UNICODE编码,所以所有的字符内容都可以转为十进制数字。**

范例:字符和整数进行比较

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        char name = '董';//中文都是有编码
        System.out.println(name == 33891);

    }
}

true

不同的数据类型彼此发生数据大小比较之后一定要发生转型问题,如果转型失败(这种明面上的数据类型,如果真有转型失败的问题,那么编译器会直接告诉使用者可能出现的语法错误)那么一定无法进行比较,所以本次字符一定是首先自动的转为整型,而后利用整型数值进行相等的判断。

范例:布尔型的相等和不等判断

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        boolean flagA = true;
        boolean flagB = false;
        System.out.println(flagA == flagB);
        System.out.println(flagA != flagB);

    }
}

false
true

由于布尔数据类型的取值范围的定义,所以在使用关系运算符进行布尔数据类型判断的时候,只能够使用相等和不等两个运算符。,而其他的关系运算符将无法使用。

三目运算符

如果同学们仅仅是在基础课程的学习过程之中实际上是很难感受到三木运算符的优势(在日后进行代码开发的过程里面,三目运算符相当的好用,同时可以帮助所有的人解决许多的代码冗余的问题)。
|- 三目运算符的本质相当于是一个带有判断的赋值运算符, 传统的赋值运算符能够设置的内容基本上就是变量或者常量,它采用都是比较直白的模式

**  如果某些值需要有条件的进行赋予则就必须进行一些关系运算符的判断处理了,当符合于某些判断条件的时候赋值,如果不符合赋予另外一个数值,而这个过程就属于三目运算符的操作,该操作的基本语法形式如下。**

语法形式:[数据类型] 变量 = 判断条件 ? 条件满足时复制内容:条件不满足时赋值内容;

范例:观察三目运算符的使用

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        int ageA = 10;
        int ageB = 15;
        int maxAge = ageA > ageB ? ageA : ageB;
        System.out.println(maxAge);
    }
}

15

对于此时的三目运算符相当于使用了一个if分支语句进行判断处理操作。

范例:三目等价于if、else判断

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        int ageA = 10;
        int ageB = 15;
        int maxAge = 0;
        if (ageA > ageB)
        {
            maxAge  = ageA;
        }
        else {
            maxAge  = ageB;
        }
        System.out.println(maxAge);
    }
}

最终输出结果同上

实际上在所有的运算符使用的过程之中都是可能存在有嵌套关系的,下面实现一个三目运算的嵌套处理。

范例:实现三目运算的嵌套

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        int ageA = 10;
        int ageB = 15;
        int ageC = 18;
        int maxAge = ageA > ageB ? ageA : ageB > ageC ? ageB : ageC ;
        System.out.println(maxAge);

    }
}

18

**  对于此时的程序的操作结构实际上是不便于阅读的,提倡编写简单代码。**

逻辑运算符

逻辑运算主要描述的是与或非这样的基本关系,使用逻辑运算符最终的特点在于可以同时连接多个判断条件。
例如:在之前使用的关系运算符,每一次只能够进行一个条件的判断,这样的操作一定不适合于更加复杂的程序逻辑。

逻辑运算符
----------------------------------------------------------
|-与(&普通与和&&短路与):若干个判断条件同时为true,最终程序结果才是true;
|-或:(|普通或||短路或)若干个判断条件有一个为true,最终程序运算的结果就是true;
|-非:(!)true变为false、false变true。
---------------------------------------------------------------------------------

** 在给出的逻辑运算符之中非运算的理解可以说是最简单的了,因为仅仅是进行了布尔求反而已**

范例:观察与逻辑

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        int x = 1;
        int y = 1;
        System.out.println(x == y & 2 > 1);
        System.out.println(x == y & 2 < 1);


    }
}

true
false

**  与的概念虽然很好理解,但是在java里面却针对于逻辑操作提供有两种不同的运算“&”、“&&”,那么这两种运算有什么区别呢。**

范例:观察普通与存在的问题

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        // 按照高等数学的逻辑来理解“数字/0 = 无求大(计算机的设计来讲无求大意味着内存占满)”
        System.out.println((1 > 2) & 10 / 0 ==0);



    }
}

Exception in thread “main” java.lang.ArithmeticException: / by zero
at DongJun.main(DongJun.java:7)

*这个时候的程序出错实际上意味着所有的判断条件都执行了,但是现在来分析一个问题:对于与操作的逻辑来讲,最大的特点是若干个判断条件如果有一个条件为False,那么最终的与逻辑的结果全部为false(中间出现多少个true都没有意义了)。 *

如果现在使用的是“&”操作意味要全部判断
想要解决程序逻辑判断的性能问题,最佳做法就是使用短路与进行操作。

范例:短路与进行操作

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        // 按照高等数学的逻辑来理解“数字/0 = 无求大(计算机的设计来讲无求大意味着内存占满)”
        System.out.println((1 > 2) && 10 / 0 ==0);
        //第一个判断条件(1>2)结果为false,后面的判断没有意义了直接停止判断,返回false




    }
}

false

范例:观察普通或

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        // 按照高等数学的逻辑来理解“数字/0 = 无求大(计算机的设计来讲无求大意味着内存占满)”
        System.out.println((1 == 2) | (10 / 0 ==0));
        //第一个判断条件(1>2)结果为false,后面的判断没有意义了直接停止判断,返回false




    }
}

Exception in thread “main” java.lang.ArithmeticException: / by zero
at DongJun.main(DongJun.java:7)

范例:使用短路或

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        // 此时的变量的定义规则为:第一个单词的字母全部小写,随后每一个单子的首字母大写
        //Java中类的定义规则:每一个单词的首字母必须大写
        // 按照高等数学的逻辑来理解“数字/0 = 无求大(计算机的设计来讲无求大意味着内存占满)”
        System.out.println((1 == 1) || (10 / 0 ==0));
        //第一个判断条件(1>2)结果为false,后面的判断没有意义了直接停止判断,返回false




    }
}

true

经过以上分析可以得到一个结论,考虑到执行性能的问题,一定要使用短路与、短路或进行若干操作。

位运算符

为了提升程序的数据处理性能,在任何的语言里面都提供有位运算符,在很多的项目开发之中一般的开发人员很难见到位运算具体的操作(大部分的位运算都出现在一些比较底层的开发过程之中),java中支持的位运算的类型有:&(位与)、|(位或)、^(异或)、~(反码)、<<(左移)、>>(右移)、>>>(无符号右移)。

如果要想使用位运算,处理的逻辑为:数字除2取余,一直除0为止,最后将所有的余数倒叙取出,下面来分析一下如何将十进制的13数字转为二进制。

面试题:请解释“&”和“&&”的区别?
    - 对于“&&”主要应用在逻辑运算中,表示短路与操作,在进行若干个条件判断的时候,如果有条件返回了false,那么后续的条件都不判断,最终的判断的结果就是false;
    - 对于“&”有两种使用环境:
        |- 逻辑运算:表示所有的判断条件都会执行,不管是否遇见有返回false的判断条件;
        |- 位运算:表示进行位与的计算,如果两位的内容都是1结果才是1,如果有一位是0,那么位与的结果就是0;

程序的逻辑结构

|- 实际上程序本身是有自己完善的逻辑性,而且从程序设计角度来讲,程序的逻辑一共分为三种逻辑:顺序结构、分支结构、循环结构。
|- 在面对程序的时候后我们就相当于“程序的上帝”,你规定了某一个程序的功能,某一个程序的处理的逻辑,所谓的程序逻辑就相当于通过自己的想法,为程序规划路线。

分支结构

所有的程序都有可能根据一些内容动态的判断是否要执行某些代码,这样的处理逻辑就称为分支逻辑,在程序的开发之中分支逻辑分为两种类型:if分支(逻辑条件判断)、switch开关语句(数值判断)。

if 分支结构

if如果直接翻译为中文的话为“如果”的含义,在使用if语句进行判断的会说话必须判断是布尔型的处理结构,针对if语句有如下是那种操作结构:
|- if (布尔表达式) { 
    当布尔表达式成立时执行语句
}

|- if (布尔表达式) { 
    当布尔表达式成立时执行语句
} else {
    条件不满足时执行语句
}

|- if (布尔表达式) { 
    当布尔表达式成立时执行语句
} else if (布尔表达式){
    当布尔表达式成立时执行语句
}……else{
    条件不满足执行
}

范例:学生成绩分支

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        double score = 190.00 ;
        if (score >= 90.00 && score <= 100)
        { 
            System.out.println("优等生");
        } else if (score >= 60 && score < 90)
        {
            System.out.println("良等生");
        } else {
            System.out.println("差等生");
        }
    }
}

Switch 开关语句

Switch是一个开关语句,在switch之中它能够判断的数据类型仅仅是:整数、字符、JDK1.5之后追加了枚举,JDK1.7之后追加了String的判断支持,如果要想使用switch必须结合case、default(不是必须)来一起使用,其基本的语法结构如下
|- switch (整数|字符|枚举|String){
    case 匹配内容:
        内容满足时执行的语句;
        [break ;]}
    case 匹配内容:{
        内容满足时执行的语句;
        [break ;]},……[
    default:{
        内容都不满足时执行;
        [break ;]}
    ]
    }

对于switch来讲,它无法像if语句那样使用逻辑表达式进行判断,仅仅支持数值操作

范例:观察switch语句

public class DongJun{
static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
public static void main(String DongJun[]){
int ch = 3;
switch(ch) {
case 1:
System.out.println(“【1】匹配的数字1”);
break ;
case 2:
System.out.println(“【2】匹配的数字2”);
break;
default:
System.out.println(“【NO】无法匹配内容”);
break;

        }
}

}

【NO】无法匹配内容

*  以上的程序的处理结构是在实际的开发之中使用switch最为常见的结构形式,但是在使用的过程之中,也有可能出现一些认识上的问题,导致最终程序的执行结果与预期有所差别,下面针对于switch中出现一些情况进行说明。**
*|- 在编写switch语句的过程之中每一次case语句中都会包含一个“break”,这个语句的含义是阻止其他功能执行

|- 不一定按照顺序来写case
|- 在早期的switch语句结构之外,除了数字之外最主要的支持就是字符了,(因为字符可以和整型自动互相转换)

在JDK1.7之后(是Oracle收购SUN之后的第一个版本)支持有String的判断,但是仅仅是进行完整的判断。

范例:在switch语句中使用String

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        String message = "我";
        switch(message){
            case "Dong":
                    System.out.println(message+"Jun");
                    break;
            case "董":
                    System.out.println(message+"俊");
                    break;
            default:
                    System.out.println("请输入正确的姓名");
                    break;

            }
    }
}

这种字符串与switch结合匹配主要使用的形式是全匹配。

yield 关键字

yield是在JDK13之后正式加入到java中的新关键字,这个关键字的主要作用是进行内容的局部返回,现阶段其主要的设计是结合switch语句来使用,下面在正式的讲解yield之前首先观察一个程序

范例:观察switch分支

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        String data = "one";
        int result = 0 ;
        switch (data){
            case "one":
                result = 1;
                break;
            case "two":
                result = 2;
                break;
            default:
                result = -1;
                break;
        }
        System.out.println(result);


    }
}

1

* 本程序的核心含义是通过switch的判断来最终决定result变量内容是什么,以上的程序开发是属于传统的做法,而传统的做法现在就觉得有些啰嗦,如果可以直接在switch里面返回数据该多好呢?*

范例:观察JDK13之后的新结构

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        String data = "one";
        int result = switch (data){
            case "one" : yield 1 ;
            case "two" : yield 2 ;
            default :{
                yield -1;
                } 
        };
        System.out.println(result);
    }
}

1

*  以上的做法实际上是局部的switch返回的简化的处理形式,如果现在不想使用“->”标记符号组合,就可以通过yield关键字来处理了*

该程序的机制实际上并没有完全的加入到java的正规使用的环境之中,还只是一种当前现阶段的测试应用环境,如果要想使用这样的功能就必须在编译和执行的时候追加“–enable-preview”参数

知识结构扩展:python语言里面有yield关键字
    |-在python中的yield也是实现了局部返回,但是它在进行局部返回的时候可以结合生成器和多协程开发进行操作。

循环结构

在java里面循环的结构分为两类:while循环、for循环,这两种循环在实际的项目开发过程之中基本上都要使用到,而且循环的结构几乎所有的项目中全部都存在。

while循环

while 是一种条件判断的循环处理,它主要是针对于给定的条件,当条件满足之后才会执行。

范例:实现”1-100”数字累加

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        int sum = 0 ;
        int num = 1 ;
        while (num <= 100) 
        {
            sum +=num;
            num ++ ;
        }
        System.out.println("sum="+sum);
    }
}

sum=5050

public class DongJun{
static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
public static void main(String DongJun[]){
int sum = 0 ;
int num = 1 ;
do
{
sum +=num;
num++ ;
}
while(num<=100);
System.out.println(“sum=”+sum);
}
}

sum = 5050

如果真的在实际的项目开发过程之中,很难见到“do……while”循环结构,在代码里面基本上只要条件的循环都以while循环结构为主。

for循环结构

如果说你已经明确知道了循环次数的时候,就可以通过for循环结构更加简单的进行循环处理,首先来观察一下for循环的语法结构
|-
  for(循环初始化条件 ; 循环判断 ; 循环条件变更){
    循环体;
  }

      可以发现在for语句结构里,将所有的循环有关的操作全部放在了一行语句完成。

范例:使用for循环

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        int sum = 0;
        for (int num = 1; num <= 100 ; num ++ )
        {
            sum += num;
        }
        System.out.println("sum="+sum);
        }
}

sum = 5050

**  需要特别引起注意的一件事情在于:对于for循环结构实际上可以拆开编写,但是在实际的开发过程中不建议如此定义**
范例:不便方式
public class DongJun{
static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
public static void main(String DongJun[]){
int sum = 0;
int num = 1;
for (; num <= 100 ; )
{
sum += num;
num ++ ;
}
System.out.println(“sum=”+sum);
}
}

以上的程序代码在实际上开发中不建议使用

while循环:当不知道明确的循环次数,但是却明确知道循环的结束条件的情况下可以使用while循环;
for循环:明确的知道循环次数的时候使用。

循环控制语句

在正常的情况下,所有的循环一旦开启了,那么肯定会按照既定的原则持续的执行下去(一直到不满足循环条件为止,循环才会自动的退出),但是在某些情况下,有可能会阻塞循环的执行。
针对于中断执行提供有两个关键字:continue、break;

结论:continue结束一次循环调用,而break是退出整个循环结构

循环嵌套

大部分的结构都是可以嵌套的,例如:在switch里面可以继续嵌套循环或者是if语句,在循环结构里面也可以嵌套if结构,那么同期,一个循环内部也一定可以嵌套另外一个循环。

**  关于循环嵌套的提醒:只要你能够编写循环,就可以正常的向后学习课程内容。**

范例:打印乘法口诀表

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        for (int x = 1; x <= 9  ; x ++ )
        {
            for (int y = 1; y <= x ; y ++)
            {
                System.out.print(y+"*"+x+"="+(x*y)+"\t");
            }
            System.out.println();
        }
    }
}

11=1
1
2=2 22=4
1
3=3 23=6 33=9
14=4 24=8 34=12 44=16
15=5 25=10 35=15 45=20 55=25
1
6=6 26=12 36=18 46=24 56=30 66=36
1
7=7 27=14 37=21 47=28 57=35 67=42 77=49
18=8 28=16 38=24 48=32 58=40 68=48 78=56 88=64
19=9 29=18 39=27 49=36 59=45 69=54 79=63 89=72 9*9=81

此时的程序利用循环嵌套实现

范例:打印正三角形

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        int line  = 5 ;//总共输出5行
        for (int x=0 ; x <5 ; x ++)
        {
            for (int y=0 ;y < line - x; y++ )
            {
                System.out.print(" ");//输出空格
            }
            for (int y=0; y <= x  ; y++ )
            {
                System.out.print("* ");
            }
            System.out.println();
        }

    }
}
 *
* *



实现了三角形的打印

|- 在现在的项目开发过程里面,如果不是必须的情况下,这种循环的嵌套代码会出现,但是不会出现的很多,而且随着你自己开发经验的累计,那么最终也一定可以熟练掌握。
|- 既然已经存在循环嵌套结构,那么就必须去讨论一下关于continue语句的问题了,在程序的开发语言里面可以发现“C”、“C++”、“Java”语法的结构都是非常类似,在C语言里面提供有了一个“goto”关键字,这种关键字在所有项目开发中都被命令禁止使用的开发关键字,因为会造成程序逻辑结构的混乱,在Java里面将“goto”关键字定义为了未使用到的关键字,如果此时在循环嵌套结构里面你非要进行一种代码跳转的实现,就可以通过continue来完成。

范例:在循环嵌套结构里面使用continue进行跳转

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        point: for (int x = 0; x <3 ; x ++ )
        {
            for (int y=0; y< 3  ;  y++)
            {
                if (x == y)
                {
                    continue point;//代码跳转
                }
                System.out.print(x + "、");
            }
            System.out.println();
        }
    }
}

1、2、2、

在内部的for循环嵌套结构里面使用了continue实现了无条件的跳转处理操作,所以最终的执行结果就出现了偏差,但是这样的程序逻辑是非常不适合阅读,所以以上的代码形式在开发中尽量不要出现

方法作用概述

方法(英文单词“method”)指的是一种可以被重复调用的代码段,如果完全没有学习过编程的概念你就把方法想象为一个功能。例如:只要你会开车,那么给你汽车你就可以直接开走(在你的开车的过程之中可能完全不知道汽车的工作原理)。

方法定义

在java里面由于方法是整个程序之中最为重要的结构,所以对于方法的定义本身也是非常繁琐的,为了方便大家理解本次讲解的方法结构,所以将采用如下的定义方式:
--------------------------------------------------------------
public static 方法返回值类型 方法名称(参数类型 变量, 参数类型 变量, ……)
{    
    方法体(本方法所需要实现的功能);
    [return 返回值;]
}

特别注意:public static本次讲解的方法指的是主类中定义,并且由主方法直接调用的处理形式

方法的定义格式:

  方法的返回值类型:主要使用的是java数据类型(基本类型、引用类型)、如果没有返回值就使用void定义;
  方法名称在java之中有明确的命名要求:第一个单词的字母小写,而后每一个单词的首字母大写;
  如果方法定义了非Void返回值类型,则可以通过return返回处理结果,如果使用了void,也可以使用return,就不需要返回具体的数据内容了

定义一个无参且无返回值的方法

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        printMessage();
        printMessage();
    }
    public static void printMessage(){//第一个单词字母小写,后续单词首字母大写
        System.out.println("******************") ;
        System.out.println("******  DJ  ******") ;
        System.out.println("******************") ;
    }                                             
}

** DJ **



** DJ **


程序之中存在有方法之后,程序代码依旧要通过主方法执行

范例:定义一个有参数有返回值的方法

public class DongJun{
static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
public static void main(String DongJun[]){
String result = payAndGet(20.0);
System.out.println(result);
//如果方法本身就存在返回值声明,那么也可以直接进行输出
System.out.println(payAndGet(9.9));

}
public static String payAndGet(double money){
    if(money >= 10.0){
        return "购买一份快餐,找零:"+ (money - 10.0);//返回一个字符串
    }
    else {
        return "对不起,你的余额不足。";
        }
}                                             

}

购买一份快餐,找零:10.0
对不起,你的余额不足。

需要注意的一个问题:如果你现在定义的方法使用了void声明了返回值类型(方法不会返回数据),那么这个时候也可以利用return语句结束当前方法调用(此时的return不应该继续返回任何内容了)

范例:使用return结束方法调用

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        sale(3);
        sale(-3);

    }
    public static void sale(int amount){
            if (amount <= 0)//设置一个判断条件
            {
                return ;//后续的语句都不在执行了(相当于break、continue概念)
            }
            System.out.println("销售出了"+amount+"李兴华");
        }
    }                                             

销售出了3李兴华

return相当于结束当前方法

方法重载

方法重载从严格意义上来讲指的是一种方法名称的重用功能,利用特定的处理机制,可以让一个方法实现不同的功能。

**  在Java程序里面方法的名称实际上和变量的名称一样,都是不能够重复的,所以如果要进行方法重载的话,那么首先要做的事情就是必须将方法名称设置为相同,但是需要针对于方法的参数进行不同的定义,方法的参数及类型要有所不同。**

范例:观察方法重载

public class DongJun{
static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
public static void main(String DongJun[]){
System.out.println(sum(10, 20));
System.out.println(sum(10, 20, 30));
System.out.println(sum(10.2, 20.3));
}
public static int sum(int x, int y) {
return x + y;
}
public static int sum(int x, int y, int z)//此时定义的sum()方法的名称重复,但是参数的个数不重复
{
return x + y + z;
}
public static double sum(double x, double y) {
return x + y;
}
}

30
60
30.5

对于以上的程序代码,本身也存在有一些设计问题

**  在java中进行方法重载的时候只是针对于方法名称和参数的类型及个数有所要求,但是并没有对方法的返回值有所要求,也就是说一个方法被重载之后可以由不同的返回值类型定义,但是这也成为了一个设计上的问题。**

为什么需要有方法重载的机制呢?

之所以提供有方法的重载,主要的目的是为了保留方法名称(有些方法名称是拥有公共特征,不应该将其隶属于某一种数据类型)
实际上在整个的java里面最具有代表性的一种重载的就属于输出的操作。

范例:观察屏幕输出

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        System.out.println(1);
        System.out.println(1.1);
        System.out.println("www");
        System.out.println('Y');
        System.out.println(true);



    }
}        

1
1.1
www
Y
true

此时可以发现“System.out.println()”(后面有括号全部表示方法调用)可以输出不同的数据类型,所以该方法本身也属于一种重载的方法。

方法递归调用

方法的递归调用属于一种方法调用的特殊形式,这种方法调用指的是就是一个方法调用自身的情况,但是在进行递归调用过程之中一定要设置好结束条件,否则依然会出现循环的问题。

范例:通过递归实现一个数字的累加
|- “1100”累加,或者是由”11000”累加,所以这种情况下可以考虑利用递归的模式完成.

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        int sum = 0;
        int num = 1000;
        while (num > 0 )
        {
            sum += num;
            num --;
        }
        System.out.println(sum);

    }
}    

public class DongJun{ 
    static int age; //如果现在没有定义具体的内容,则应该使用默认值“0”来表示
    public static void main(String DongJun[]){
        int result = sum(1000);
        System.out.println(result);
    }
    public static int sum(int num) {
        if (num == 0) {
            return 0;
        }
         return num + sum(num - 1); //递归调用

    }
}                                             

500500

为了便于理解,下面针对于当前给定的sum()递归调用进行一个简单的操作说明:

    【第一次调用】由“main()”方法发出:return 10000+sum(9999);
    【第二次调用】由“main()”方法发出:return 9999+sum(9998);
    【倒数第二次调用】由“main()”方法发出:return 1+sum(0);
    【倒数第二次调用】由“main()”方法发出:return 0;
由于递归操作较为繁琐,而且一旦处理不当那么就有可能在代码的执行过程之中出现内存溢出的问题(需要一些栈内存支持),所以如果不是必须的情况下尽量不要去编写递归调用(在java开发过程里面实际上你也不会使用递归。)

面向对象概述

在整个的java(连同C++一样)最为复杂繁琐的部分就是面向对象的编程了,但是如果说现在我们都不知道面向对象的程序结构是什么,而仅仅是进行一些概念上的细分,实际上就属于极为不厚道的讲法。
在编程语言项目的发展历史过程之中,早期的项目设计结构使用的是“面向过程”,面向过程最大的特点是解决当前的问题。
而面向对象是在面向过程之上的进一步的技术发展,面向对象最大的一个特点在于进行标准化的设计,也就是说它在进行项目开发之前一定要对不同层次的功能的整合进行详细的说明。

**  面向对象的设计之中,除了拥有模块化的设计结构之外,实际上还有三个重要的特点:**

|- 封装性:程序内部的处理结构对外不可见(结构内部不可见、实现结构不可见);
- 实现结构不可见:不同的层之间进行处理的时候可以完全不知道具体的实现细节;
- 内部结构不可见:内部的相关的核心定义外部无法直接访问,这就与访问权限相关了;
|- 继承性:在先人的基础上继续发展,就好比如果参考进化论,每一位人祖先都是猿人,肯定每一代都要比上一代要强,利用继承的结构划分出不同的类关系,同时保证一些公共的特征存留下来。
|- 多态性:多态是一种不确定的执行模式,同样的一个功能不同的人干会有不同的方法,但是最终的目的都是在解决核心的问题。

面向对象之中会有许多更加细节化的概念,那么这些概念都需要时间慢慢沉淀,对于面向对象本身并不是世界上唯一使用编程模型,也有许多的开发者愿意使用面向过程或者函数式的编程,而java采用的是面向对象的开发,从本质上来讲这样的代码写起来有些难受(要求的语法结构非常细致),但是最大的特点是易于阅读。

类与对象

如果要想研究面向对象的编程技术,那么首先一定要明确的就是类与对象的关系,因为这个关系是整个面向对象编程之中基本组成单元,类描述的是一类事物的共同特征的集合(概念是不能够直接使用的),而对象描述的是一个体化拥有鲜明特点的实物。

**  在每一个类之中都会有相关的属性和行为(方法),所谓的行为描述的就是类的功能,所有的对象都可以去调用类中定义的功能。**

在进行面向对象设计之中一定要先进行类结构的定义,而后才可以拥有具体的对象,对象是可以直接使用的操作;
一个类可以产生多个对象,不同的对象拥有各自不同的特点(属性),但是所有的对象都拥有相同的功能(方法)。
|- 专业描述:类是对象共性的集合,而对象是类的实例,类必须依靠对象实例才可以使用。

类与对象的定义

在之前所编写的所有的程序代码都是在一个类中进行程序的定义,在之前分析过了“public class”、"class"定义类的基本区别,实际上在java中程序类主要就是通过class关键字进行定义的,所以定义的基础语法结构如下):
------------------------------------------------
class 类名称 { //遵守命名规则,每个单词的首字母大写
    [访问修饰符] 数据类型 成员属性(变量);
    [访问修饰符] 数据类型 成员属性(变量);
        ... ... ...
    [访问修饰符] 返回值类型 方法名称 (参数类型 参数1 ...){
        本方法处理语句;
        [return [];]
    }
}
------------------------------------------------
一个类中可以同时定义多个成员属性(FIeld)、也可以定义多个方法(Method),在进行属性定义前出现的“访问修饰符”最终的作用就是实现类的封装性的特点,本次针对于修饰符采用不定义(默认的形式),而方法中出现的访问修饰符统一使用“public”来进行描述。

范例:定义一个描述图书信息的类

|- 声明并实例化对象: 类名称 对象名称(变量) = new 类名称();
|- 进行分步定义,整个的操作分为两个处理阶段:
    - 声明对象:类名称 对象名称 = null(引用数据类型的默认值);
    - 实例化对象: 对象名称 = new 类名称();

当一个类已经产生了实例化对象之后肯定要对类结构进行操作,在java程序里面,对象可以通过两类语法形式使用类:
|- 调用类中的成员属性(Field):实例化对象.属性= 值;

|- 调用类中的方法(Method):实例化对象.方法名称();

范例:声明并实例化对象

class Book
{
    //图书的名称肯定是多位字符
    String title;
    String author;
    //价格一定是一个小数,double的准确性高于float
    double price;
    public void getInfo() { //本次定义getInfo()方法过程之中可以发现没有使用最初讲解方法时的“static”关键字,在之前讲解方法时在主类中定义的,而现在在类中定义的方法主要通过对象来进行调用,所以此时暂时不加static,具体语法后续会有详细解释。
        System.out.println("图书名称:"+ title + "、图书作者:" + author + "、图书价格:" + price);
    }
}

public class DongJun //主类
{
    public static void main(String avgs[]){
        Book book = new Book();
        book.title = "我的";
        book.author = "天啊";
        book.price = 89.6 ; 
        book.getInfo();
    }
}

图书名称:我的、图书作者:天啊、图书价格:89.6

*  此时的程序代码已经可以通过类产生的实例化对象进行类中结构的调用了,实例化对象一旦出现,类的结构就可以进行各种操作的,而本次的操作仅仅是进行了一些属性的设置以及方法的调用**
*观察属性默认值

class Book
{
    //图书的名称肯定是多位字符
    String title;
    String author;
    //价格一定是一个小数,double的准确性高于float
    double price;
    public void getInfo() { //本次定义getInfo()方法过程之中可以发现没有使用最初讲解方法时的“static”关键字,在之前讲解方法时在主类中定义的,而现在在类中定义的方法主要通过对象来进行调用,所以此时暂时不加static,具体语法后续会有详细解释。
        System.out.println("图书名称:"+ title + "、图书作者:" + author + "、图书价格:" + price);
    }
}

public class DongJun //主类
{
    public static void main(String avgs[]){
        Book book = new Book();
        book.getInfo();
    }
}

图书名称:null、图书作者:null、图书价格:0.0

**  现在程序仅仅是进行了book类对象的实例化处理,随后在没有进行属性设置的情况下立即调用getInfo()方法获取对象内容,通过结果可以发现title、author内容全部为null(String 是一个类,类是引用数据类型,默认值就是null)而price的默认值为“0.0”。**

一个类与对象的基本概念已经讲述完毕,同时以上给出的语法结构实际上也属于实际开发过程之中的常规的操作形式了,但是为了帮助大家更好理解面向对象设计与之前概念的联系,下面利用面向对象的设计形式来实现一个正三角形的打印,而这个打印过程里面,将通过属性来保存打印的行数。

范例:面向对象设计的应用

class Triangle 
{
    int line = 5 ;
    public void paint() {
        for (int x = 0; x< line ; x++)
        {
            for (int y = 0;  y< line - x; y++ )
            {
                System.out.print(" ");
            }
            for (int y = 0 ;y <= x ; y++ )
            {
                System.out.print("* ");
            }
            System.out.println();
        }
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
        Triangle tri = new Triangle();
        tri.line = 3;
        tri.paint();
    }
}

*

  • *

**  在之前实现此功能的时候要么就直接在主方法里面进行定义,要么就直接定义有一个方法进行调用,但是现在将与这个图形有关的成员属性(变量)和操作方法混合定义在了一个“Triangle”类里面,从代码管理来讲,结构是非常清晰的。**

对象内存分析

在之前已经为大家讲解过了整个java之中的数据类型划分,而对于数据类型的划分,在Java里面分为两类:基本数据类型(数值的传递操作)、引用数据类型(内存地址的传递,这种引用传递就类似于C、C++之中的指针的概念)

**  所有的数据都要保存在内存之中,但是如何可以准确的获取数据,就称为了计算机操作系统本身需要解决的问题,那么经过了长期的发展之后,人们发现应该将内存的功能分为两个部分:**

|- 【heap】 堆内存:是保存对象的真实信息;
|- 【stack】栈内存:保存的是对象的堆内存的地址;

对于所有的内存的操作实际上每一位开发者是完全不知情的,所有与内存分配有关的任何操作全部都是由JVM负责完成的,不同的操作系统之中内存分配机制肯定也是不同的,那么最终全部由JVM进行分配

如果要想进行对象属性或方法的操作,一定要保证存在有实例化对象(开辟了堆内存的对象、或者有堆指向的实例)

引用传递分析

Java之中引用数据类型需要内存的支持,所以在进行程序开发的过程之中,内存是可以有多个指向,内存的多个指向指的是不同的栈内存可以指向同一个堆内存。

垃圾产生分析

在Java语言里面有一个最为重要的技术特点:垃圾回收(Garbage Collector),所有的数据都要保存在内存之中,但是内存里面也是需要进行顺序式的空间分配,如果要想非常深入的去理解垃圾回收的相关操作,那么就需要先明白垃圾是什么?如何产生的,随后才可以进一步的优化
Java提供有自动的GC回收机制,但是如果你的程序之中产生的垃圾过多,那么也会造成硬件性能的损耗,从而导致程序的执行性能下降,所以最佳的做法是避免垃圾的产生。

成员属性的私有化

|- 在面向对象的设计之中有三大主要特征(封装、继承、多态),封装是在面向对象设计之中最为常见的一种概念,但是如果要思想把封装的所有概念都弄明白,则还需要充分的理解继承与多态,本次所讲解的成员属性私有化就是封装的一种基础实现。
|- 按照一般程序的设计思路来讲,如果要想使用类肯定要通过对象,类中一般会提供有属性和方法,那么不同的对象可以进行属性的操作,传统的做法是直接在类的外部由实例化对象直接进行属性的操作。

范例:使用private关键字定义类中属性

class Book
{
    private String title;
    private String author;
    private double price;
    public void getInfo(){
        System.out.println("图书标题:"+ title + "\n图书作者:"+ author +"\n图书价格:"+ price);
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
        Book book = new Book();
        book.title = "成长日记";
        book.author = "董俊";
        book.price = 99.9; 
        book.getInfo();



    }
}

DongJun.java:14: 错误: title 在 Book 中是 private 访问控制
book.title = “成长日记”;
^
DongJun.java:15: 错误: author 在 Book 中是 private 访问控制
book.author = “董俊”;
^
DongJun.java:16: 错误: price 在 Book 中是 private 访问控制
book.price = 99.9;

使用private关键字定义类中属性所以无法访问

使用了private外部的对象无法直接访问了,但是类的内部是可以进行访问的,于是如果要想进行private私有属性的访问操作,按照Java本身定义规则来讲,就需要编写setter、getter方法来完成 
|- stter:进行属性内容的设置,基本形式:
-------------------------------------------
public void set 属性名称(属性类型 变量){ 属性名称 = 变量}
private String title;
public void setTitle(String t){
    title = t;    
}
|- getter:获取属性内容:基本的形式:
--------------------------------------
public 属性类型 get属性名称(){
    return 属性名称;
}
public String getTitle(){
    return title;
}

你的类中不管有多少属性都需要编写与之匹配的setter、getter的方法的个数,而且这种编写的设计结构是所有的Java后续开发之中都一定会使用的模式。

范例:观察private属性访问

class Book
{
private String title;
private String author;
private double price;
public void setTitle(String t){
title = t;
}
public void setAuthor(String a){
author = a;
}
public void setPrice(double p)
{
price = p;
}
public String getTitle(){
return title;
}
public String getAuthor(){
return author;
}
public double getPrice()
{
return price;
}

}
public class DongJun //主类
{
public static void main(String avgs[]){
Book book = new Book();
book.setTitle(“我行得正”);
book.setAuthor(“做的好”);
book.setPrice(88);
System.out.println(“图书名:”+book.getTitle()+book.getAuthor()+book.getPrice());
}
}

图书名:我行得正做的好88.0

在日后整个程序的开发过程之中,只要编写类中的属性一定要使用private进行声明,而private声明的属性必须要与之匹配的setter、getter方法才可以被外部所访问,即便当前的代码里面没有调用全部方法,但是作为一个标准类的功能这些方法都是必须提供出来的。

构造方法

构造方法是Java类之中的一种特殊形式的操作方法,其调用的时机是在对象实例化的时候(堆内存开辟的时候进行调用),下面首先来观察一下构造方法的基本形式;

范例:观察构造方法

class Book
{
    public Book(){//构造方法
        System.out.println("******董俊来*******");
    }
}
public class DongJun
{
    public static void main(String args[])
    {
        System.out.println("【1】声明book类对象:“Book book = null; ”");
        Book book = null; 
        System.out.println("【2】实例化book类对象:“book = new Book();”");
        book = new Book();//实例化对象
    }
}

【1】声明book类对象:“Book book = null; ”
【2】实例化book类对象:“book = new Book();”

在整个程序执行过程之中,真正进行构造方法调用的位置处就是使用关键字“new”实例化对象的时候,实际上对于此时的操作,Book类中就定义了构造方法,但是对于构造方法本身是有其非常严格的定义要求的:

|- 构造方法的方法名称不能够任意编写,必须与类名称保持一致;
    - 此时定义的类是类名称是Book,而构造方法的名称使用的是“public Book(){}”;
|- 构造方法没有返回值声明,并且不能够返回任何的数据内容;
|- 一个类之中如果没有定义任何的构造方法,则会在程序编译的时候自动由JDK生成一个无参的构造方法。

构造方法在现实中的应用;

|- 构造方法是在使用关键字new的时候才会被调用,而且一个对象只会执行一次构造操作,就好比一个人只能出生一次;
|- 如果现在类中没有通过构造方法进行属性内容的设置,那么就意味着整个的程序在对象实例化之后所有的成员属性都是默认值,那么就需要一步一步的进行属性的配置,就好比书先封装好了,随后再往里面填充内容,最终形成成品。

  如果现在一个类种即要求有参构造也要求提供无参构造的时候后,唯一可以使用的方法就是通过方法的重载形式来完成,但是需要注意的是,此时只需要考虑方法的参数类型及个数即可(因为构造方法的名称和类名称是完全相同的)

观察方法的重载

class Book
{
    private String title;
    private String author;
    private double price;
    public Book(){}
    public Book(String t){
        this.setTitle(t);
        this.setAuthor("沐言优拓");
        this.setPrice(90.1);
    }
    public Book(String t, String a, double p)
    {
        setTitle(t);
        this.setAuthor(a);
        setPrice(p);
    }
    public void getInfo(){
        System.out.println("图书标题:"+ title + "\n图书作者:"+ author +"\n图书价格:"+ price);
    }
    public void setTitle(String t){
        title = t;
    }
    public void setAuthor(String a){
        author = a;
    }
    public void setPrice(double p){
        price = p;
    }

}
public class DongJun //主类
{
    public static void main(String avgs[]){
        Book book = new Book("董俊","2",89.0);
        book.getInfo();
    }
}

本程序在Book类中定义有三个构造方法:无参构造、单参构造以及三参构造,需要注意的是构造方法本身没有明确的顺序要求,但是考虑到代码的结构性的特点,按照采用参数的降序排列或者升序排列

类中构造方法和类中的普通方法的定义有什么区?

*  类的构造方法只在使用关键字new实例化新对象的时候调用一次,而有了实例化对象之后,就可以利用该对象重复的调用类中定义的普通方法。*

  • 如果现在构造方法不返回任何数据,那么为什么不能够使用void定义呢?
    构造方法的名称是由大小写要求的,但是如果仅仅是凭借名称实际上编译器是无法区别构造方法还是普通方法。
如果从方法定义的角度来讲,JDK是依据结构来区分构造或是普通方法的,如果加上了void,实际上就变为了普通方法。

匿名对象

匿名本质上的含义指的就是没有名字,而匿名对象本质上的核心思想就是没有名字的对象。

范例:观察匿名对象的使用

class Book {
    private String title;
    private String author;
    private double price;
    public Book(){};    //无参构造方法
    public Book(String t){     //单参构造方法
        this.setTitle(t);
        this.setAuthor("沐言优拓");
        this.setPrice(-1.0);
        }
    public Book(String t, String a, double p){
        setTitle(t);
        this.setAuthor(a);
        setPrice(p);
    }
    public void getInfo() {
        System.out.println("图书名称:"+title+"、图书作者:"+ author + "、图书价格:"+ price);
    }
    public void setTitle(String t){
        title = t;
    }
    public void setAuthor(String a){
        author = a;
    }
    public void setPrice(double p) {
        if (p > 0)
        {
            price = p;
        }
    }
    public String getTitle(){
        return title;
    }
    public String getAuthor(){
        return author;
    }
    public double getPrice(){
        return price;
    }
}
public class YootkDemo{
    public static void main(String args[]){
         new Book("从入门到时间","董俊",99).getInfo(); // 声明并实例化
         new Book("从入门到时间").getInfo();
         new Book().getInfo();
    }
}

此时通过关键字new创建的book类的实例化对象,那么就属于一个匿名对象,因为没有对象名称对其进行引用(之前分析了:通过对象名称可以让对象调用多次的操作,如果没有对象名称了,那么该对象就没有引用了,这个对象在使用一次之后就会成为垃圾对象了,那么这个时候有同学可能就不理解了,为什么要有匿名对象呢?)
现在假设有这样一种生活场景:我是一个卖视频的商铺,因为我的生意非常的火爆,所以我没有时间为我制作的每一件商品命名

范例:使用匿名对象

class Food
{
    private String name;
    private double price;
    public Food(String n, double p){
        name = n;
        price = p;
    }
        //setter、getter略
        public String getInfo(){
            return "名称:"+name + "、价格:" +price;    
        }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
        for (int x= 0;x <100  ; x ++ )
        {
            sale(new Food("西红柿烤烧饼",7.9);
        }
    }
    public static void sale(Food temp){
        System.out.println("【卖出商品】"+ temp.getInfo());
    }
}

当然,以上的代码也可以使用有名对象,例如:先为food实例化对象命名,随后在通过对象名称进行操作

this 关键字

如果要是以java中的关键字使用为例,个人觉得this关键字是比较繁琐的一个关键字,因为this在程序开发之中使用较为灵活,它可以根据不同的环境而有所改变,而且使用this关键字进行处理操作的过程之中,可以描述是那种处理含义:成员属性、方法(普通方法、构造方法)、表示当前对象。

this 调用本类成员属性

在一个类中定义的许多的成员属性都可以互相进行调用,例如:某一个属性可能在构造方法中被调用,那么也可能在普通方法中进行调用,只要是在一个类中那么就都可以实现这样的处理。

范例:观察之前编写过的一个代码

class Book
{
    private String title;
    private String author;
    private double price;
    public Book(String t, String a, double p ){
        title = t;
        author = a ;
        price = p ;
    }
    public String getInfo(){
        return "【图书信息】书名:"+this.title + "、作者:"+ this.author + "、价格:"+ this.price;
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
        Book book = new Book("入门到实战","董俊",90);
        System.out.println(book.getInfo());
    }
}

【图书信息】书名:入门到实战、作者:董俊、价格:90.0

以上的程序代码是在之前经常编写过的程序逻辑,但是对于当前的程序代码里面有一处的设计是非常不合理的,这一处指的就是类中定义的构造方法,来观察一下构造方法的定义:
|- 
    public Book(String t, String a, double p ){
    title = t;
    author = a ;
    price = p ;
    }
这个时候的构造方法里面需要传递有三个参数,并且这三个参数名称使用了单个字母描述,那么请问,如果按照正常的标识符的定义要求来讲,这样的标识符虽然符合语法意义,但是不符合于实际的“明确要求”,因为字母t、a、p可能描述的单词范围太多了,那么这个时候最佳的做法肯定是希望可以写上全部的名称

范例:修改程序实现正确的赋值

class Book
{
    private String title;
    private String author;
    private double price;
    public Book(String title, String author, double price ){
        //一旦使用了“this.属性”,那么就永恒描述的是类中的成员耐属性。
        this.title = title;
        this.author = author ;
        this.price = price ;
    }
    public String getInfo(){
        return "【图书信息】书名:"+this.title + "、作者:"+ this.author + "、价格:"+ this.price;
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
        Book book = new Book("入门到实战","董俊",90);
        System.out.println(book.getInfo());
    }
}

【图书信息】书名:入门到实战、作者:董俊、价格:90.0

在以后编写代码的过程之中,只要是访问本类中的成员属性的操作里面一定要采用“this.属性”的形式进行明确的指派,我曾经个人在编写代码的时候就因为有一个地方少写了 this,最终发现执行的结果缺少内容 ,我排查了好久之后才发现的问题。

调用本类的普通方法

在一个类之中往往会存在有大量的普通方法,这些普通方法每当获取了该类的实例化对象之后,那么都可以直接进行调用,而如果要在本类中进行方法调用的时候,理论上直接使用方法名称即可,但是也可以使用"this.方法()"的形式进行更加明确的调用(两者效果相同,但是后者的编写形式更好)。

范例:观察本类的方法调用

class Book
{
    private String title;
    private String author;
    private double price;
    public Book() {}
    public Book(String title, String author, double price ){
        setTitle(title);
        setAuthor(author);
        setPrice(price); //调用本类方法
    }
    public void set(String title, String author, double price) {
        setTitle(title);
        setAuthor(author);
        setPrice(price); //调用本类方法
    }
    public void setTitle(String title) {
        this.title =  title;
    }
    public void setAuthor(String author){
        this.author = author;
    }
    public void setPrice(double price){
        this.price = price ;
    }
    public String getTitle() {
        return this.title;
    }
    public String getAuthor() {
        return this.author;
    }
    public double getPrice() {
        return this.price;
    }
    public String getInfo(){
        return "【图书信息】书名:"+this.title + "、作者:"+ this.author + "、价格:"+ this.price;
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
        Book bookA = new Book("入门到实战","董俊",90);
        System.out.println(bookA.getInfo());
        Book bookB = new Book();
        bookB.set("Python从入门到实战","李兴华",98.8);
        System.out.println(bookB.getInfo());
    }
}

【图书信息】书名:入门到实战、作者:董俊、价格:90.0
【图书信息】书名:Python从入门到实战、作者:李兴华、价格:98.8

按照正常的设计思维来讲,类之中的普通方法调用的形式应该为“对象.方法()”,但是如果要是在本类之中调用本类的方法时候可以直接编写方法名称,而如果要想更加明确的描述调用本类方法的话则最好编写的形式为"this.方法()"

构造方法互调用

|- 一个类之中构造方法是允许进行重载的,在进行构造方法重载的过程之中只需要考虑方法的参数类型及个数的不同即可,所以一个类里面构造方法可能有很多,那么在这样的环境下就可以考虑利用"this()"的形式实现构造方法的互相调用,这种互相调用的机制也仅仅是使用一次(构造方法只能够调用一次,是在新对象开辟堆内存空间的时候使用)。
|- 既然所有的对象进行实例化的时候都一定会进行构造方法的调用,那么假设说现在类中存在有三个构造方法,分别描述的是无参构造、单参构造、三参构造,那么这个时候不管是调用了那一个构造方法,都可能执行某些操作(输出一些重要的信息),那么按照原始的做法代码有可能定义为如下的形式:

范例:采用原始的形式实现固定操作的执行

class Book
{
    public Book() { 
        System.out.println("【对象创建提示】");//想象为30行代码
        }
    public Book(String title) {//单参
        System.out.println("【对象创建提示】");//想象为30行代码
    }
    public Book(String title, String author, double price ){//多参
        System.out.println("【对象创建提示】");//想象为30行代码
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
            new Book("java实战","董俊",89);
            new Book("java实战");
            new Book();
        }
}

【对象创建提示】
【对象创建提示】
【对象创建提示】

此时的程序已经实现了之前提出的开发要求,只要是进行新对象的创建,则一定要进行提示信息的输出,但是这个时候也可以发现一个问题:对于某些操作重复的在代码中出现了,按照之前所讲解的形式,如果要想解决重复,那么一般可以考虑使用方法进行包装,那么只需要每一次调用特定的方法就可以解决重复代码定义问题。

范例:利用方法的形式解决代码重复

class Book
{
    public Book() { 
        this.initObject();
        }
    public Book(String title) {//单参
        this.initObject();
    }
    public Book(String title, String author, double price ){//多参
        this.initObject();
    }
    public void initObject() { // 信息提示
        System.out.println("【对象创建提示】");//想象为30行代码
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
            new Book("java实战","董俊",89);
            new Book("java实战");
            new Book();
        }
}

【对象创建提示】
【对象创建提示】
【对象创建提示】

虽然这个时候进行了重复代码的方法定义,并且在构造方法之中通过"this.initObject()"方法执行了重复的代码,但是你也会发现此时的程序代码中也存在有设计问题,会发现不同的构造方法里面调用了同样的方法,实际上这个时候后又是一种重复,那么为了解决当前的这种重复的设计,最佳的做法是直接进行构造方法的互调用

范例:利用this实现构造方法的互调用

class Book
{
    private String title;
    private String author; 
    private double price;
    public Book() { 
        System.out.println("【对象创建提示】");//想象为30行代码
        }
    public Book(String title) {//单参
        this();
        this.title = title;
    }
    public Book(String title, String author, double price ){//多参
        this(title);//调用无参构造
        this.title = title;
        this.author = author;
        this.price = price;
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
            new Book("java实战","董俊",89);
            new Book("java实战");
            new Book();
        }
}

【对象创建提示】
【对象创建提示】
【对象创建提示】

此时利用了"this()"的语法形式实现了类中不用构造方法的互相调用,并且通过具体的操作实现也可以发现,这种结构的确是比方法抽象更加节约对象初始化代码的效果,但是对于当前的这种语法也需要考虑如下几个问题:
|- 使用"this()"调用构造方法处理的时候必须放在构造方法的首行,因为构造方法是在类对象实例化的时候首先调用的,所以其必须放在构造内,而不同的构造方法有可能存在有不同的顺序问题,所以才将其放在首行。
|- 使用构造方法互相调用的时候一定要保留有出口,否则在程序编译的时候就会直接出现递归错误信息,所以这样程序代码在编译的时候就会直接报错。

既然已经清楚了构造方法之间的互相调用,那么下面就可以针对于这种互相调用进行一次实际的应用说明,现在假设说有一个Book类(包含有三个成员属性"title"、“author”、“price”),这个类中会提供有三种构造方法
    — 无参构造:要求图书名称为“木言优拓”,作者为“李兴华”,价格为9988.66;
    — 单参构造:要求接受图书名称,但是默认情况下的作者为“小李老师”,几个5566.88;
    — 三参构造:要求接受全部的三个成员属性的内容。

先不去考虑重用性设计直接编写原始代码

class Book
{
    private String title;
    private String author; 
    private double price;
    public Book() { 
            this.title = "木言优拓";
            this.author = "李兴华";
            this.price = 9988.66;
        }
    public Book(String title) {//单参
            this.title = title;
            this.author = "小李老师";
            this.price = 5566.88;
        }

    public Book(String title, String author, double price ){//多参
            this.title = title;
            this.author = author;
            this.price = price;

    }
    public String getInfo(){
        return "图书名称:" + this.title + "、图书作者:"+ this.author + "、图书价格:" +this.price;
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
            Book bookA = new Book();
            Book bookB = new Book("从java到入门");
            Book bookC = new Book("从python到入门","李兴华",99.8);
            System.out.println(bookA.getInfo());
            System.out.println(bookB.getInfo());
            System.out.println(bookC.getInfo());
        }
}

图书名称:木言优拓、图书作者:李兴华、图书价格:9988.66
图书名称:从java到入门、图书作者:小李老师、图书价格:5566.88
图书名称:从python到入门、图书作者:李兴华、图书价格:99.8

此时程序已经完成了既定的开发要求,但是也可以明确的发现所有重复的操作代码,那么在这样的情况下就可以考虑利用构造方法的互调用来解决当前的重复操作问题。

解决构造方法中的重复代码

class Book
{
    private String title;
    private String author; 
    private double price;
    public Book() { 
            this("木言优拓","李兴华",9988.66);
        }
    public Book(String title) {//单参
            this(title,"小李老师",5566.88);
        }

    public Book(String title, String author, double price ){//多参
            this.title = title;
            this.author = author;
            this.price = price;

    }
    public String getInfo(){
        return "图书名称:" + this.title + "、图书作者:"+ this.author + "、图书价格:" +this.price;
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
            Book bookA = new Book();
            Book bookB = new Book("从java到入门");
            Book bookC = new Book("从python到入门","李兴华",99.8);
            System.out.println(bookA.getInfo());
            System.out.println(bookB.getInfo());
            System.out.println(bookC.getInfo());
        }
}

图书名称:木言优拓、图书作者:李兴华、图书价格:9988.66
图书名称:从java到入门、图书作者:小李老师、图书价格:5566.88
图书名称:从python到入门、图书作者:李兴华、图书价格:99.8

构造方法的主要作用是进行成员初始化操作,但是在成员属性初始化的过程之中难免会存在有重复的初始化的操作代码,所以这个时候利用构造方法来解决是最合理的一种做法。

this 表示当前对象

经过了之前一系列分析可以发现,对于this有一个最为常见的调用类结构的操作形式:“this.成员属性”、“this.方法()”,那么根据在之前所学习的概念来讲,类中的属性或方法可以调用的只能够是实例化对象(如果使用了没有实例化的对象,则一定会出现“NullPointerException”),所以之前的语法之中的this本质上描述的就是一个对象,但是这个对象不是一个固定的对象,而是描述的当前对象概念。
    一般的拥有浪漫气息的节日里面,酒店或者一些客房的预订最为繁华的,例如:红色情人节需要准备,如果是白色情人节也可以准备,如果是浪漫的圣诞结更需要准备。

如果要想观察出程序里面的当前对象,最简单的做法就是直接进行this关键字的输出,默认情况下每一个实例化对象的输出应该得到的就是一个对象的编码

观察实例化对象的直接输出

class Book{}
public class DongJun //主类
{
    public static void main(String avgs[]){
            Book bookA = new Book();
            System.out.println("【main()方法】 = " + bookA);
            Book bookB = new Book();
            System.out.println("【main()方法】 = " + bookB);
    }
}

【main()方法】 = Book@63961c42
【main()方法】 = Book@65b54208

Java中的类属于引用数据类型,引用数据类型之中需要去考虑堆栈的引用关系,发现如果直接进行对象的输出所获得的就是一个对象的编码,而这种编码的格式为“类名称@编码”(这个是由Java内部默认决定的程序结构)。

范例:观察this与对象的关联

class Book{
public void print() {
System.out.println(“【Book类-print()方法】”+this);
}
}
public class DongJun //主类
{
public static void main(String avgs[]){
Book bookA = new Book();
System.out.println(“【main()方法】 = “ + bookA);
bookA.print();
System.out.println(“—————- 防止 —————- “);
Book bookB = new Book();
System.out.println(“【main()方法】 = “ + bookB);
bookB.print();
}
}

【main()方法】 = Book@63961c42
【Book类-print()方法】Book@63961c42
—————- 防止 —————-
【main()方法】 = Book@65b54208
【Book类-print()方法】Book@65b54208

范例:使用this实现引用传递

class Message 
{
    private String title;
    private String content;
    private Channel channel;
    public Message(Channel channel, String title, String content){
        this.title = title;
        this.content= content;
        this.channel = channel;
    }
    public void send() {
        if (this.channel.connect())
        {
            System.out.println("【Message】消息发送,消息标题:"+ this.title + "、消息内容:" + this.content);
            this.channel.close();
        } else {
            System.out.println("【Message】没有可用的消息发送通道,消息发送失败");
        }
    }
}
class Channel
{
    private Message message;
    public Channel(String title, String content){
        this.message = new Message(this, title, content);
        this.message.send();
    }
    public boolean connect() {
        System.out.println("【Channel】建立消息信息的发送通道");
        return true;
    }
    public void close() {
        System.out.println("【Channel】关闭消息信息的发送通道");
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
        Channel channel = new Channel("木言优拓在线教育","编程训练营");
    }
}

【Channel】建立消息信息的发送通道
【Message】消息发送,消息标题:木言优拓在线教育、消息内容:编程训练营
【Channel】关闭消息信息的发送通道

现在是在Channel类里面实例化了Message类的独享,所以这个时候如果直接出现有"this",那么所描述的就是当前channel的对象。

简单Java类

在整个的Java技术学习过程之中,首先一定要明确一个核心的问题:学习一门语言如果要想尽快的上手开发,那么就必须熟练的掌握一些核心的编程模型(数学公式),只要遇见了相似的程序按照公式的形式直接定义好即可。
本次重点来研究关于简单Java类的定义,实际上从项目的开发角度来讲,使用类有一个最为核心的功能,它能够描述有一类群体的共性特征。
简单Java类指的是一个类之中主要由属性以及setter、getter方法所组成的类,这个类不牵扯到各种复杂的运算逻辑,仅仅是进行相关数据的存储,同时这种类一般都有明确的实物类型,例如:定义一个描述部门的信息类、定义一个描述雇员的信息类、定义一个描述教师的程序类。
在Java里面随着技术学习的不断深入,你会慢慢更加深刻的了解简单java类的实际使用,包括一些设计上的不断的改良,但是对于现在来讲,给出如下的简单java类的开发要求:
|- 【必选】类名称一定要有意义,可以明确的描述某一类的事物特征;
|- 【必选】类之中所有的属性都必须使用private封装;
|- 【必选】如果要进行属性点设置或者是修改则一定要通过setter方法完成,而属性的获取要通过getter;
|- 【必选】类之中可以定义若干个构造方法,但是一定要提供有一个无参构造方法(需要通过反射机制研究);
|- 【必选】对象中的所有信息不允许直接在类中使用"System.out.println()"输出,所有的输出内容一定要返回给被调用处来进行输出处理
|- 【可选】类中要提供有一个返回对象信息的处理方式;

范例定义一个描述部门信息的简单java类

|- 假设现在部门信息里面需要包含有部门编号、名称以及位置三个核心属性。

class Dept
{
    private long deptno ; 
    private String dname;
    private String loc;
    public Dept(){}
    public Dept(long deptno, String dname, String loc ){
        this.deptno=deptno;
        this.dname= dname;
        this.loc = loc ;
    }
    public void setDeptno(long deptno){
        this.deptno=deptno;
    }
    public void setDname(String dname){
        this.dname = dname;
    }
    public void setLoc(String loc){
        this.loc = loc ;
    }
    public long getDeptno()
    {
        return this.deptno;
    }
    public String getDname(){
        return this.dname;
    }
    public String getLoc(){
        return this.loc;
    }
    public String getInfo() {
        return "【部门】部门编号:" + this.deptno + "、部门名称:" + this.dname  + "、部门位置:" + this.loc;
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
        Dept dept = new Dept(10, "沐言有哦" , "北京");
        System.out.println(dept.getInfo());
    }
}

【部门】部门编号:10、部门名称:沐言有哦、部门位置:北京

对于此时的Dept类功能非常的单一,就是进行了数据的保存以及数据的获取,所以这个类不涉及到任何的运算逻辑,就被开发中称为简单java类。
重要提示:简单java类是最基础的模型,但是其可以考察以及覆盖的知识点是非常全面的
    |- 类的基本组成:属性、方法(构造方法、普通方法);
    |- 数据类型的选择:基本类型、引用类型(后面会有更加深入的分析);
    |- 构造方法的重载;
    |- 属性的封装有以及setter、getter方法的定义要求;
    |- 字符串的连接操作。

类与对象实例分析

面向对象是所有初学者学习的难点,实际上在我个人学习的过程之中,对于面向对象想起来都觉得头大,因为其所涉及的概念是非常的多的,有其实很多的同学学到现在的时候就会突然发懵:不知道什么时简单java类,什么又不是简单java类,针对于这样的情况,本次为大家分析三道程序案例。

地址类

问题一:编写并测试一个代表地址的Address类,地址信息由国家、省份、城市、街道、邮编组成,并可以返回完整地址信息。

对于此时的设计开发要求本身并没有过多的繁琐,因为在之前所编写的图书类、部门类等等都与该类的结构非常的相似,所以这种类严格来讲就属于一个简单java类

class Address 
{
    // 属性private封装
    private String country;
    private String province;
    private String city;
    private String street;
    private String zipcode;
    public Address(){}
    public Address(String country, String province, String city, String street, String zipcode)
    {
        this.country = country;
        this.province = province;
        this.city = city;
        this.street = street;
        this.zipcode = zipcode;
    }
    public String getInfo(){
        return "【Address】国家:"+ this.country +"、省份:" + this.province + "、城市:" + this.city + "、街道:"+ this.street + "、邮编:"+ this.zipcode;
    }
    public void setCountry(String country){
         this.country = country;
    }
    public void setProvince(String province){
        this.province = province;
    }
    public void setCity(String city){
        this.city = city;
    }
    public void setStreet(String street){
        this.street = street;
    }
    public void setZipcode(String Zipcode){
        this.zipcode = zipcode;
    }
    public String getCountry(String country){
        return this.country;
    }
    public String getProvince(String province){
        return this.province;
    }
    public String getCity(String city){
        return this.city;
    }
    public String getStreet(String street){
        return this.street;
    }
    public String getZipcode(String zipcode){
        return this.zipcode;
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
        Address addr = new Address("中国","湖北","武汉","新洲区","00000");
        System.out.println(addr.getInfo());
    }
}

【Address】国家:中国、省份:湖北、城市:武汉、街道:新洲区、邮编:00000

对于这样的程序开发啊,其本身属于简单java类,如果连这样的基本程序都不能够保证一次性写对(可以快速的修改正确),那么就不建议你使用任何的开发工具进行代码编写

员工信息类

定义并测试一个代表员工的Employee类。员工属性包括“编号”、“姓名”、“基本薪水”、“薪水增长率”,还包括计算薪水增长额及计算增长后的工资总额的操作方法。同时在该类中要提供有四个构造方法:
【无参构造】编号定义为1000,姓名定义为无名氏,其他内容均为默认值;
【单参构造】传递编号,姓名定义为“新员工”,基本薪水为3000.00,薪水增长率为1%;
【三参构造】传递编号、姓名、基本工资、薪水增长率为5%;
【四参构造】所有的属性全部进行传递。

题目分析:这个程序并不能算是一个完全的简单java类,因为这个类里面包含有一部分的业务处理逻辑(逻辑计算),但是其整体操作结构依然是进行数据的存储。

范例:定义并使用员工类

class Employee
{
    private long empno ;
    private String ename ;
    private double salary;
    private double rate;
    // setter、getter操作略…… , 实际代码之中一定要写上这些方法
    public Employee() {
        this(1000, "无名氏",0.0, 0.0);
    }
    public Employee(long empno) {
        this(empno, "新员工",3000.00,0.01);

    }
    public Employee(long empno, String ename , double salary ){
        this(empno, ename, salary, 0.05);
    }
    public Employee(long empno, String ename, double salary, double rate){
        this.empno = empno;
        this.ename = ename;
        this.salary = salary;
        this.rate = rate;
    }
    public double salaryIncValue(){
        this.salary  = this.salary * (1 + this.rate) ;
        return this.salary ;
    }
    public String getInfo(){
        return "【Employee】员工编号:"+ this.empno + "、员工姓名:"+ this.ename + "、基本工资:"+ this.salary + "、增长额:" + this.rate;
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
        Employee emp = new Employee(9527,"周星星",5000.0,0.1);
        System.out.println(emp.getInfo());
        System.out.println("工资增长:"+emp.salaryIncValue());

    }
}

【Employee】员工编号:9527、员工姓名:周星星、基本工资:5000.0、增长额:0.1
工资增长:5500.0

本程序虽然核心的组成结构为简单java类,但是这里面却有了一些程序的处理逻辑存在,所以这种情况下,依然要按照简单java类组成原则进行定义,而对于一些逻辑的处理操作方法额外追加即可。

用户登录逻辑

习题要求:设计一个表示用户的User类,类中的变量有用户名、口令、定义类的3个构造方法(无参、为用户名赋值、为用户名和口令赋值)、获取和设置口令的方法和返回类信息的方法,同时编写一个进行登录验证的处理操作逻辑。

题目分析:对于当前的程序逻辑定义类的母的是为了进行用户登录,如果说没有用户登录的验证需求,那么这个时候就是一个纯粹的简单java类,但是发现有了用户登录验证的需求之后,对于当前的程序逻辑就不再是一个简单的存储了。

范例:实现用户的登录验证

class User
{
    private String name ;
    private String password;
    public User(){
        this(null,null);
    }
    public User(String name){
        this(name, null);
    }
    public User(String name, String password){
        this.name = name ;
        this.password = password;
    }
    public boolean isLogin(String tempName, String tempPassword) {
        return tempName.equals(this.name) && tempPassword.equals(this.password);
    }
}
public class DongJun //主类
{
    public static void main(String avgs[]){
        User user = new User("董俊","123");
        if (user.isLogin("董俊","123"))
        {
            System.out.println("用户登录成功,可以开始进行程序访问!");
        } else {
                    System.out.println("用户登录失败,错误的用户名和密码!");
        }
    }
}

用户登录成功,可以开始进行程序访问!

此时程序类是一个功能性的操作类,他不再是一个简单java类,因为让其存储的是核心的业务处理逻辑。

本文标题:JAVASE

文章作者:孤桜懶契

发布时间:2020年09月21日 - 09:18:27

最后更新:2021年10月20日 - 13:11:07

原始链接:https://gylq.gitee.io/posts/18.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------------本文结束 感谢您的阅读-------------------