学编程,来源栈;先学习,再交钱
当前系列: 编程语言 修改讲义

复习:强弱类型

预定义类型

又被称之为:基本类型、内置类型、常用类型。大意是由语法规定的,内置于语法中,最常用的那些类型。

数值

数值(numeric)类型分为整数小数

1)整数

根据“最多能够存储的数值大小”,将整数分为:

  • byte:8位
  • short:16位
  • int:32位
  • long:64位
上述所称的“位(bit)”,又被称之为“长度(Length)”,是指变量以二进制形式存储时,能够占据的空间(复习:二进制存储容量)。我们可以把1位,想象成1格,每一格都只能存放1或0。所以:
  • 1位,只能存2个(2的1次方,用2^1表示)数字:1和0,最大为1;
  • 2位,只能存4个(2^2)数字:00/01/10/11,最大为11(二进制)
  • 3位,只能存8个(2^3)数字:000/001/010/011/100/101/110/111,最大为111
  • ……
  • 8位,就能够存2^8个数字,最大为11111111,转换为十进制:2^8-1=255

但是,除了byte,short/int/long都是既能存正数,也能存负数,所以需要额外占用一位(格)来存正/负符号,所以他们的存储范围是 -2^(n-1) 到 2^(n-1)

可以直接通过类型.MinValue或MaxValue查看:(Java不能直接这样操作,详见包装类型

short.MinValue
short.MaxValue

超过最大存储数值的赋值会报错:

    byte b = 255;   //OK
    byte b = 257;   //报错
    short s = 257;  //OK

我们实际开发中,最常用的是int类型;I/O文件流时,会使用到byte。

注意:区分"32"和32,有引号(“”)和没引号

2)小数

计算机中小数的存储比整数麻烦一些,但大体上来说,小数也可以说是“按能存储的数值的大小”区分:

  • float(浮点/单精度):32位
  • double(双精度,默认):64位
PS:以上位数中还要包含:正负位、小数点、指数、尾数

但是,对于小数来说,存储容量不仅仅可以决定存储数值的大小,还可以决定存储数值的“精度”(小数点后位数)。

@想一想@:0.000000001虽然很小,但是不是和存储1000000000这种很大的数一样,需要很大的存储空间?

一般场景(默认)我们使用double就OK啦:

    float score = 85.5F;    //不要忘了F后缀
    double avgScore = 92.32345;    //可以不要后缀

小心精度问题,(复习:0.1+0.2==0.3),对比:

            float fee = 98.000000000006F;
            double fee = 98.000000000006;

            Console.WriteLine(fee);

布尔值

C#中写作bool,Java中boolean:值只能是true/false,(和JavaScript不同)不能是1/0啥的……

字符和字符串

  • char:字符,始终是单个的,包括字母(如a)、数字(如1)、运算符号(如+)、标点符号(如。)和其他符号(如~),以及一些功能性符号(如ctrl)。实际开发中用得不多,但它是字符串的基础。
    注意:Java/C#中:
    1. 一个字符变量只能存储一个字符
    2. 字符用引号('')包裹
  • string(Java中大写S,即:String):字符串,在编程开发中大量使用,本质上就是由一个一个的字符“串”起来的。关于她的内容实现机制,后文会有详述……字符串用引号(“”)包裹
    char source = '源';
    string welcome = "源栈欢迎您";


类型转换

相关(近似,比如数值类型)间可以有:

  • 隐式(自动):短变长
    int age = 23;
    long lage = age;             //int可隐式转换成long
    char yuan = '源';
    int iYuan = yuan;    //char对应的是字符编码
    复习:编码
  • 显式(强制):长变短
    short sAge = (short)age;     //int转换成short需要显式转换,注意可能有“精度”损失
    //string strAge = (string)age; //无法在“大类”之间进行强制转换

注意:

  • 检查能否转换的标准是变量类型,不是变量的值。这种检查又被称之为:类型/编译时/静态检查,对应的是值/运行时/动态检查。
  • 慎用显式转换!
    double fee = 98.6;
    Console.WriteLine((int)fee);  //98:小数转整数还好
    
    int big = 986217324;
    Console.WriteLine((short)big);   //31596:整数转整数就崩了……
    因为转换是在二进制层面进行的,然后再由二进制再转成十进制。

另:在完全不兼容类型间转换,需要使用类库函数,详见后文:C#/Java/JavaScript


运算

算术

需要注意的是:整数除以整数,结果还是整数。要想结果为小数,除数或被除数,至少要有一个是小数:

    Console.WriteLine(12 / 5);  //结果为2
    Console.WriteLine(12F / 5); //结果为2.4
    Console.WriteLine(12 / 5F); //结果为2.4

比较

  • 不是所有类型的数据之间都可以进行比较:
        bool result = "3" > 2;   //报错
        bool result = 3.5M > 2.2;   //报错
  • 比较之后的结果是一个bool值,所以:
        bool easier = 1.5/0.5 > 0.5/0.3;

逻辑

||和&&只能用于bool值,不能应用于整数等:
    Console.WriteLine(1 || 0);   //报错

|和&只能用于int值(???

    //位或可以应用于整数和bool值
    Console.WriteLine(1 | 0 );
    Console.WriteLine(2 | 4);   /*猜一猜结果是多少?*/

选择运算符(?:)只能用于赋值,不能用于其它。

字符串

拼接(+):除了可以拼接字符串,还可以拼接字符串和其他类型变量(如整数/小数/布尔值)


数组

强类型语言在声明一个数组(变量)时必须指定其类型。数组中能存放元素类型决定了数组类型,如:

    double[] scores;    //注意这个方括号([]),一个double类型数组
一经声明,该数组里的所有元素都只能是这种类型的数据。

数组变量本身(不是其元素)需要被赋值后才能使用:

double[] scores;
//1、这就是在使用未被赋值的scores了
//2、这不是在给scores赋值,是在给scores[0]赋值
scores[0] = 100;  

和我们之前学习的变量赋值使用“字面量”不同,数组的值需要

初始化

    double[] scores= new double[3];    //[3]是必须的,指定了数组的长度Length(元素个数)

这时候,数组仍然是“空”的。

注意:两种“空”是不一样的

    double[] scores;           //null:变量中没有存储任何东西
    names = new double[5];    //empty:变量里已经“有”了一个数组,只是数组中每个元素都是空的

断点演示:watch null和double[3]

这样初始化之后,数组里的每个元素都有一个默认值(数值:0,bool:false,字符串:null)

还可以在初始化的时候指定数组元素的值:

    double[] scores = new double[] {98, 68, 89.5 };//没有指定数组元素个数

上述写法还可以进一步简化:(语法糖,new的过程并未省略)

    double[] scores = { 98, 78, 85.5 };  //仅在给数组赋值时使用

越界错误

当超过数组最大下标,使用一个数组中元素时,就会报数组越界错误:

注意这就是运行时(runtime)错误,对比:编译时(compile)错误


方法

面向对象中函数被称之为方法method,定义略有不同

声明

必须声明在class中,比如Program{}(是Main(){}中):

        static double min(double[] scores)
        {
              return -1;
        }

PS:同学们先不要管这个static,直到我告诉大家它是什么之前,所有方法都先加上这个关键字

方法签名(signature)

定义了方法的:
  • 返回类型:double,也可以是其他类型,比如int、string……具体由开发人员决定。
    如果方法签名中声明的返回类型为void,意味着这个方法返回任何实际性的数据。
  • 名称:min,一样由开发人员确定(参考:命名规则)
  • 参数:double[] scores,其中又包括了参数的:
    • 类型:double[],
    • 名字:scores

方法的返回类型和方法名都只能有一个而且必须有一个,参数可以没有,也可以有多个

方法体:code path检查

强类型语言,返回值的类型必须和方法签名中返回类型一致,比如这样是不行的:

除非方法返回类型设置为void,否则方法体中 至少 会有一条return语句。

当方法体中出现 if...else 之类的分支,要确保所有code path(分支)都有return语句。

        static double min(double[] scores, bool first)
        {
            if (first)
            {
                return -1;
            }
            //报错:if有返回值了,else呢?
        }
而且这是 编译时 审查,你可以理解成“形式”检查。即哪怕这个分支永远永远都不会进入,它也要有一个return语句:
        static double min(double[] scores, bool first)
        {
            int i = 10;
            if (i > 5)
            {
                return -1;
            }
            //哪怕i=10,10总是大于5,仍然报错!
        }
PS:如果不是使用变量 i,直接 if(10>5)或者const int i=10,就可以编译通过,因为常量和字面量会在编译时直接处理,得出10>5永远为true,就不会将其视为一个分支。

调用

方法调用的位置和变量一样,现在我们都在Main(){}中进行调用。

复习/介绍快捷键:F11 / Shift+F11

传递参数时,需要匹配方法声明中参数的

  • 个数:方法声明中要求2个参数,你调用时给1个或者3个都是不行的
  • 顺序:传递进来的数据,将按次序依次赋值给方法参数,不要搞错了次序(尤其是在参数类型相同的时候)
  • 类型:每一个传入的数据类型,必须和方法声明中参数类型一致


作业

  1. 将之前JavaScript书写的代码,用C#或Java重写一遍。(面向函数部分除外)
    前提:已安装相关IDE,并能将作业推送到github

提醒:非常重要,是接下来学习“面向对象”的基础

学习笔记
源栈学历
键盘敲烂,月薪过万作业不做,等于没学

作业

觉得很 ,不要忘记分享哟!

任何问题,都可以直接加 QQ群:273534701

在当前系列 编程语言 中继续学习:

多快好省!前端后端,线上线下,名师精讲

  • 先学习,后付费;
  • 不满意,不要钱。
  • 编程培训班,我就选源栈

更多了解 加:

QQ群:273534701

答疑解惑,远程debug……

B站 源栈-小九 的直播间

写代码要保持微笑 (๑•̀ㅂ•́)و✧

公众号:源栈一起帮

二维码