自学js第三天:JS数据类型及其转换

JavaScript 的数据类型

JavaScript 语言的每一个值,都属于某一种数据类型。JavaScript 的数据类型,共有七种。

一.据类型广义分类

传统分类通过存储位置 把数据类型分为 基本数据类型 和 引用数据类型

基础类型存储在栈内存中 ,引用数据类型存储在堆内存中.  
Undefined、Null、Boolean、Number、String和symbol  (java的string是引用类型存在方法区内存中)

在这里插入图片描述

二.JS的数据类型具体分类:

  • 数值(number):整数和小数(比如13.14

    (类似Java的byte/short/int/float/double/long全部数值类的一起梭哈)
  • 字符串(string):文本(比如'Hello World')。

  • 布尔值(boolean):表示真伪的两个特殊值,即true(真)和false(假)

  • undefined:表示“数值未定义”,即undefined由于目前数值没有任何值,是作为默认值

  • null:表示"空值对象不存在",即此处的对象值为空。

  • 对象(object):各种值组成的集合。

  • symbol (symbol ) : 唯一标识符 //es6学习前不做讨论

PS1:数值、字符串、布尔值这三种类型,合称为原始类型(primitive type)的值,即它们是最基本的数据类型,不能再细分了。
PS2:对象Object则称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。
PS3:至于undefined和null,一般将它们看成即是两个数据类型,又是两个属性值。

1.深入Number 类型.(整数和浮点数值)

(类似Java的byte/short/int/float/double/long全部数值类的一起梭哈,也因此会出现精度丢失问题无法分辨,因此很多小数计算都会出现问题,因此计算数据不能在前端进行,只能在服务端上精准实现)

  • (1)Number作为整数数值 : (十进制整数/八进制/十六进制)
 各种进制问题:

十进制
	var num = 9;
	进行算数计算时,八进制和十六进制表示的数值最终都将被转换成十进制数值。

十六进制
	var num = 0xA;
	数字序列范围:0~9以及A~F

八进制
    var num1 = 07;   // 对应十进制的7
    var num2 = 019;  // 对应十进制的19
    var num3 = 08;   // 对应十进制的8
    数字序列范围:0~7
    如果字面值中的数值超出了范围,那么前导零将被忽略,后面的数值将被当作十进制数值解析
  • (2)Number作为小数浮点数值

①浮点数的精度问题(精度丢失问题严重)

浮点数
	var n = 5e-324;   // 科学计数法  5乘以10的-324次方  
浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数
   var result = 0.1 + 0.2;    // 结果不是 0.3,而是:0.30000000000000004,js很奇葩...
   console.log(0.07 * 100);
   不要判断两个浮点数是否相等

java因为数值数据类型有着从小到大严格体系 , 因此只在数据类型强制转换(大转小)的时候,才会出现精度丢失问题.

②浮点数值精度深入(了解浮点数值的最高精度是17位的小数)

根据国际标准 IEEE 754,JavaScript 浮点数的64个二进制位,从最左边开始,是这样组成的。

  • 第1位:符号位,0表示正数,1表示负数
  • 第2位到第12位(共11位):指数部分
  • 第13位到第64位(共52位):小数部分(即有效数字)

符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。

指数部分一共有11个二进制位,因此大小范围就是0到2047。IEEE 754 规定,如果指数部分的值在0到2047之间(不含两个端点),那么有效数字的第一位默认总是1,不保存在64位浮点数之中。也就是说,有效数字这时总是1.xx...xx的形式,其中xx..xx的部分保存在64位浮点数之中,最长可能为52位。因此,JavaScript 提供的有效数字最长为53个二进制位。

(-1)^符号位 * 1.xx...xx * 2^指数部分

上面公式是正常情况下(指数部分在0到2047之间),一个数在 JavaScript 内部实际的表示形式。

精度最多只能到53个二进制位,这意味着,绝对值小于2的53次方的整数,即-253到253,都可以精确表示。

③浮点数值值范围(了解)

根据标准,64位浮点数的指数部分的长度是11个二进制位,意味着指数部分的最大值是2047(2的11次方减1)。也就是说,64位浮点数的指数部分的值最大为2047,分出一半表示负数,则 JavaScript 能够表示的数值范围为21024到2-1023(开区间),超出这个范围的数无法表示。

如果一个数大于等于2的1024次方,那么就会发生“正向溢出”,即 JavaScript 无法表示这么大的数,这时就会返回Infinity正无穷大。

(3)Number的数值最大值和最小值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jfx7Mkiy-1620233715691)(C:\Users\tuyue\AppData\Local\Temp\1614854370842.png)]

Number最小值:Number.MIN_VALUE,这个值为: 5e-324   这个e代表10的幂的指数,5*10^-324次方
Number最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+3081.7976931348623157*10^308
无穷大:Infinity
无穷小:-Infinity
(4)用isNAN方法进行Number数值类型判断:

因为js是弱类型语言,所以很松散无厘头,竟然支持非法计算:“数值-字符串” 这种,只能用NAN去代表你这不是数值,是非法数.

  • 1.NaN值:not a number (非法数值)

    PS1:NAN通常在非法的数值计算会出现.

    PS2:NaN 与任何值都不相等,包括他本身(即NAN===NAN 是为false的)

  • 2.isNaN方法:是一个方法用来判断是否为NAN非法数值.

    PS:方法返回的是一个布尔类型
    PS:如下例子

<script>	
	var x = 10;
    var y = 10 - 'f';//js无厘头支持非法计算:数值-字符串
    console.log(y)//这种非法计算,会得出NAN非法数值

    //NAN非法数很特殊,NAN与任何值都不相等,包括NAN本省
    console.log(typeof y === 'NaN'); //false  NAN与任何数都不相等
    console.log(y === NaN); //false   NAN与NAN自身比较也无法相等

//不要弄混
//上面是指NAN不能拿来比较的问题(也不是不能比较而是NAN和任何数比较都为false) 
// 下面是指一个参数是不是NAN非法数的问题.
  
  //只能通过isNAN方法,通过返回布尔类型,来判断一个实/形参数,是不是 ("非法数")
    console.log(isNaN(y)); //true   是非法数
    console.log(isNaN(NaN)); //true   是非法数
    console.log(isNaN("小明")); //true  是非法数,因为该文字字符串无法转为数字

    console.log(isNaN(10)); //false    不是非法数 ,是整数
    console.log(isNaN("10")); //false   不是非法数,可以转为整数
    console.log(isNaN(true)); //false  不是非法数,可以转为1

   <script/>	 

PS:下面就是直接的语法报错了,变量没声明也没赋具体值,就拿去输出的…

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LvKLCbyT-1620233715693)(C:\Users\tuyue\AppData\Local\Temp\1614864192731.png)]

2.深入String字符串类型

  • (1)字符串字面值:带有引号的

    ‘海牙老师 真的帅’

  • (2)熟悉转义符

在这里插入图片描述

1.一般很少转义,因为JS里面可以单引号和双引号一起使用,因此内容要使用双引号的时候,我们外层就单引号就OK
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-to9SAHUj-1620233715700)(C:\Users\tuyue\AppData\Local\Temp\1614878457990.png)]

2.还可以使用转义符转义中文和符号:

​ https://www.bejson.com/convert/unicode_chinese/

注: Unicode 码表查询地址 https://www.ltool.net/characters-to-unicode-charts-in-simplified-chinese.php

  • (3)获取字符串长度 (只读,无法修改)

    length属性用来获取字符串的长度

    var str = '海牙 Hello World';
    console.log(str.length);
    
  • (4)按数组下标取字符串某个值(但也是只读,无法修改改写)
    var str = 'hello world!';
    console.log(str[1]); //e
    str[1] = 'x'; //无法改写 
    
  • (5)如何字符串拼接

    字符串拼接使用 + 号连接

    console.log(11 + 11);
    console.log('hello' + ' world');
    console.log('100' + '100');
    console.log('11' + 32);
    console.log('male:' + true);
    
    1. 两边只要有一个是字符串,那么+号就是字符串拼接功能

    2. 两边如果都是数字,那么+ 号就是算术功能。

  • (6)关于字符串的换行,(一个字符串双引号内 , 无法直接换行)
    //要不就一个引号一个引号的内容好好写
    var longString = '第一行 '
      + '第二行 '
      + '第三行 '
      + '文本内容';
      
    //用反斜杠形式进行,一个字符串引号内可以换行
    var longString = '第一行 \     
    第二行 \
    第三行 \
    文本内容';
    
    longString
    //
    

3.深入Boolean布尔类型

布尔值代表“真”和“假”两个状态。“真”用关键字true表示,“假”用关键字false表示。布尔值只有这两个值。

  • Boolean字面量: true和false,区分大小写的

  • 计算机内部存储:true为1,false为0 ,比较时用==双等会自动转化(true为1,false为0)

    (在js里面 1>2>3)

4.Undefined和Null的区别!

1.(null是js弃子,Undefined才是相当于其他语言的null)

nullundefined都可以表示“没有”,含义非常相似。将一个变量赋值为undefinednull,老实说,语法效果几乎没区别。

  1. undefined表示一个声明了没有赋值的变量,变量只声明的时候值默认是undefined.
    (只要不是null, 都会声明都会预分配内存了, 只是未定义但有默认值undefined)
  2. null表示一个空,变量的值如果想为null,必须手动设置null.
    (释放内存,不占位置,不让你占)
    (java里面,null表示对象没了,为空,则会出现空指针异常,被gc垃圾回收器回收掉,即也是释放内存一种手段)
java中大体分为,基本数据类型和引用数据类型,
java中细分为(局部变量)/(实例变量)
1.基本数据类型(int i),声明它就在栈中分配了空间,当运行时,还会附上初始值.

2.引用数据类型(Object obj):在声明它的时候即那个局部变量引用,也是在栈中分配内存空间,用来存储内存地址,
①如果没有赋值该地址指向一个默认值空值(null),这和js的undefined一样作用.!!!!
②如果赋值,则该地址指向存储在堆中分配的地址,即开始new对象时,则在堆中就会开辟分配一个新内存地址给对象,
③如是其他对象赋值给它的,这时只是栈中的地址和原地址指向同一个堆,并没有在内存中分配新的堆空间(这也叫浅拷贝,引用复制)
④深拷贝:


3.
局部变量:(局部私有变量)
定义在方法中或方法的参数列表(或者语句中)
存在于栈内存中,作用的范围结束,变量空间自动释放,方法结束,自动销毁
默认没有初始化值,使用时需要进行初始化


实例变量又称成员变量:(this有关)

成员变量定义在类中,在整个类中都可以被访问

成员变量随着对象的建立而建立,随对象的消失而消失,存在于对象所在的对内存中

成员变量有默认初始值




静态变量又称类变量:用static修饰
存储在方法区中
随着类的加载而存在,随着类的消失而消失
可以由类名或对象调用

伪代码说明:
public class Variable{     
    static int a = 0;        //静态变量,默认0
    String b = "hello world";//实例变量,默认null
    Wife w ;                   // w是实例变量 Variable有一个妻子
    
    public void method(){        
        int c = 0;           //局部变量
        Variable var = new Variable(); // var也是局部变量来的
    }
}

本文介绍成员变量和局部变量的区别:
1、成员变量是独立于方法外的变量,局部变量是类的方法中的变量
1)、成员变量:包括实例变量和类变量,用static修饰的是类变量,不用static修饰的是实例变量,所有类的成员变量可以通过this来引用。
2)、局部变量:包括形参,方法局部变量,代码块局部变量,存在于方法的参数列表和方法定义中以及代码块中。
2、成员变量可以被public,protect,private,static等修饰符修饰,而局部变量不能被控制修饰符及 static修饰;两者都可以定义成final型。
3、成员变量存储在堆,局部变量存储在栈。局部变量的作用域仅限于定义它的方法,在该方法的外部无法访问它。成员变量的作用域在整个类内部都是可见的,所有成员方法都可以使用它。如果访问权限允许,还可以在类的外部使用成员变量。
4、局部变量的生存周期与方法的执行期相同。当方法执行到定义局部变量的语句时,局部变量被创建;执行到它所在的作用域的最后一条语句时,局部变量被销毁。类的成员变量,如果是实例成员变量,它和对象的生存期相同。而静态成员变量的生存期是整个程序运行期。
5、成员变量在累加载或实例被创建时,系统自动分配内存空间,并在分配空间后自动为成员变量指定初始化值,初始化值为默认值,基本类型的默认值为0,复合类型的默认值为null。(被final修饰且没有static的必须显式赋值),局部变量在定义后必须经过显式初始化后才能使用,系统不会为局部变量执行初始化。
6、局部变量可以和成员变量 同名,且在使用时,局部变量具有更高的优先级,直接使用同名访问,访问的是局部变量,如需要访问成员变量可以用this.变量名访问

成员变量和局部变量的区别:
1、静态变量。bai 由static修饰du的变量称为静态变量,zhi其实质上就是一个全dao局变量。如果某个zhuan内容是被所有对象所共shu享,那么该内容就应该用静态修饰;没有被静态修饰的内容,其实是属于对象的特殊描述。
2、成员变量
研究一个事物(类),其有:
属性:外在特征;例如人的身高,体重,(对应class成员变量)
行为:能够做什么;例如人有说话,打球等行为。(成员函数)
3、成员变量和静态变量的区别
1、两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象被回收而释放。
静态变量随着类的加载而存在,随着类的消失而消失。
2、调用方式不同
成员变量只能被对象调用。
静态变量可以被对象调用,还可以被类名调用。
3、别名不同
成员变量也称为实例变量。
静态变量也称为类变量。
4、数据存储位置不同
成员变量存储在堆内存的对象中,所以也叫对象的特有数据。
静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。

2.历史原因:

在javascript设计初期 null就像在 Java 里一样,被当成一个对象。初像 Java 一样,只设置了null表示"无"。根据 C 语言的传统,null可以自动转为0。 但是javascript并没有完整的ERROR机制 null可以转换为0 对于javascript这种弱类型的语言来说 不利于发现bug 所以设计了 undefined 变量默认值也就成为了 undefined

所以在学习javascript的过程中 不能用java等编程语言的null来理解javascript中的null

在javascript中 null是 对象的延伸 是一个 ‘空’ 对象。var str = '';'' 不能用null判断 他是有值的 内存中分配了空间来存储 '' 一个空字符串值。
null在javascript中常见于释放内存空间和不传参数 var str = null;

3、目前的undefined和null各自用法

但是,上面这样的区分,在实践中很快就被证明不可行。目前,null和undefined基本是同义的,只有一些细微的差别。

null表示"没有对象了,对象没了",即该处不应该有值。 典型用法是:

(1) 作为函数的参数,表示该函数的参数不是对象了。

(2) 作为对象原型链的终点(释放内存)。

Object.getPrototypeOf(Object.prototype)
// null

**undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。**典型用法是:

(1)变量被声明了,但没有赋值时,就等于undefined。 js特有

(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。 js特有

(3)对象没有赋值的属性,该属性的值为undefined。 =java的null

(4)函数没有返回值时,默认返回undefined。 js特有

var i;
i // undefined

function f(x){console.log(x)}
f() // undefined

var  o = new Object();
o.p // undefined

var x = f();
x // undefined

三.一个值的类型判断

JavaScript 有三种方法,可以确定一个值到底是什么类型。

  • typeof运算符 (最常用)
  • instanceof运算符 (亲子鉴定)
  • Object.prototype.toString方法
1.typeof(什么值的类型都能判断,死记下面的总结)
1.数值(含NAN非法数)、字符串、布尔值分别返回小写的number类型、string类型、boolean类型,
2.undefined值 和 未定义的变量 返回undefined 类型,
3.array数组和object对象都是 返回的是 object类型
4.null 值 返回object 类型 //js的null很坑,null在js是归为对象object类型

PS1:关于 null 在关系运算和相等运算中的坑:

null > 0   // null 尝试转型为number , 则为0 . 所以结果为 false, 
null >= 0  // null 尝试转为number ,则为0 , 结果为 true. 
null == 0  // null在设计上,在此处不尝试转型. 所以 结果为false. 

PS2: isFinite对于其他的数值(包括:null空值)都会返回true`

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>类型判断 typeof isNaN isfinite</title>
</head>

<body>
  <script>
    //typeof 什么都能判断.
  
    //判断数据类型
    console.log(typeof String);    //function函数String类接口
    console.log(typeof Number);   //function函数Number类接口
    console.log(typeof Object); //function函数 Object类接口
    console.log(typeof Boolean); //function函数Boolean类接口
     function fn() {}
	console.log(typeof fn);//function
	
 
    console.log(typeof 'string');  //string类型
    console.log(typeof 'number');   //string类型
    console.log(typeof 'object'); //string类型
    console.log(typeof 'boolean'); //string类型
      
     //正常如果直接打小写的数据类型boolean出来会当成一个未定义的数值报错,
	//但是typeof例外,未定义的也能判断并且不报错
    console.log(typeof string);  //undefined类型
    console.log(typeof number);   //undefined类型
    console.log(typeof object);//undefined类型
    console.log(typeof boolean); //undefined类型
      
     //即是类型又是属性值的 
    console.log(typeof undefined);//即为属性值,同时还是undefined类型
    console.log(typeof null);  //即为属性值,但js把null归为object类型,很乱
    
    
    //特殊的属性值
    console.log(typeof null);  //即为属性值,但js把null归为object类型,很乱
    console.log(typeof NaN);//NaN归为number类型

   
   //1.通过借用判断属性值,来判断类型
    console.log(typeof 1);    //number
    console.log(typeof '1');  //string
    console.log(typeof false);   //boolean
    console.log(typeof NaN);//NaN归为number类型

    //2.通过判断表达式结果即也是属性值,来判断类型
    console.log(typeof 'abc'.length); //number
    console.log(typeof (1 < 2) );//boolean
      

     //PS:这里已经不是typeof了,而是先typeof的表达式结果是什么类型,再次进一步判断===问题
    console.log(typeof (1 < 2) === "boolean" ); //true
     //为什么是true,普及!!!
    //因为console.log打印出来的结果是转化为字符串的,
     //如果直接打小写的数据类型boolean出来会当成一个未定义的数值报错
     //而===是严格比较,比完类型,不同直接false,相同再比数值大小然后再是否相等
    //==是宽松比较,比完类型不同,也会一直帮你自动转换类型,看看尽力帮你相等  
      
    //如下例子:  
    console.log("boolean" === "boolean" ); //true
    console.log(typeof (1 < 2) === boolean ); //报错,boolean未定义
    console.log(1==1);//true
    console.log(1===1);//true
    console.log(1=="1");//true
    console.log(1==="1");//false
    console.log(1 === true );//false   类型不同,直接pass
    console.log(1 == true );//true     true转为1,1=1
    console.log("1"=== true );//false  类型不同直接pass
    console.log("1" == true ); //true  true转为1,"1"转为1
    

	//甚至可以
    console.log(typeof a); //可以判断未声明的变量类型,undefined
    console.log(typeof b); //可以判断未声明的变量类型undefined
    console.log(typeof c);//可以先斩后奏 类型为undefined
    var c = 'x';
    console.log(typeof c);// string类型

    console.log(typeof c === 'number' && isNaN(x));//false


    console.log(isFinite(null));  //true

    
    var x = 1;
    console.log(x + null);

  </script>
</body>

</html>

typeof 甚至可以针对未声明的v变量而不报错的 , 只是会定义为undefined类型.

if (typeof v === "undefined" ) {
   console.log("变量 v 不存在")
}
2.isNaN (isNAN主要是用来判断number数值类型是否为NAN,并返回一个布尔类型)
因此用来判断其他类型没有意义 ,因为isNAN判断其他类型都会触发Number()方法先,看能否先转为number数值,再去看是否为NAN非法数,是则true)

isNaN方法可以用来判断一个值是否为NaN非法数。

//isNAN判断其他类型都会触发Number()方法
console.log(isNaN(NaN));// true  已经是NAN了...

isNaN(123) // false    123数值

isNaN('123') // flase  数字字符串可以转123
// 触发了Number方法相当于
isNaN(Number('123')) // false

isNaN('Hello') // true  文字字符串不可转数值
// 触发了Number方法相当于
isNaN(Number('Hello')) // true

这一点要特别引起注意。也就是说,isNaNtrue的值,并不代表数值就是NaN这个值,

而是有可能是一个文字字符串,数组,对象等。如下

//下面代码之所以返回false不是非法数,统一的原因都是这些触发Number函数全部转成数值.

//Array数组
    x=[];
    console.log(isNaN(x)); //false ,空数组自身不是非法数 
    x=[123];
    console.log(isNaN(x)); //flase , 数值数组不是非法数 
    x=["123"];
    console.log(isNaN(x)); //false ,数值字符串数组不是非法数 
    x=["xyz"];
    console.log(isNaN(x)); //true ,文字字符串数组是非法数 
    x=["哈哈哈"];
    console.log(isNaN(x)); //true ,文字字符串数组是非法数 
    x=[{s}];
    console.log(isNaN(x)); //true ,对象数组是非法数 
    
   
    //对象obj
    x={};
    console.log(isNaN(x)); //true ,对象都是非法数 
    var s;
    s = new String();
    x={s};
    console.log(isNaN(x)); // true ,对象都是非法数 
  
 
    //String字符串,看是什么字符串
    x=" ";
    console.log(isNaN(x)); //false ,空字符串是不是非法数 
    x="xyz";
    console.log(isNaN(x)); //true
    x="123";
    console.log(isNaN(x)); //false

  </script>

因此,综上所处,使用isNaN之前,最好判断一下数据类型。

(因为isNAN就是用来判断是不是NAN这个具体数值的,而不是判断文字字符串和数组和对象是不是NAN的,没意义了.)

function myIsNaN(value) {
  return typeof value === 'number' && isNaN(value); 
    //这个 && 要同时为true才返回true, 因此如果typeof value不是===一个number 就已经可以返回flase了
    //已经没有比较意义了,要在前面typeof value === 'number'这个成立为true,即为数值时,才去
	//下一步isNaN(value)到底是不是NAN这一操作.
}

判断NaN更可靠的方法是,利用NaN为唯一不等于自身的值的这个特点,进行判断。

function myIsNaN(value) {
  return value !== value; 
    //这里return 表达式是用于表示判断是否相等,如果相等返回true即value不是NAN,因为NAN不与任何数相等
}
3.isFinite(是否为正常范围的有限数字)

isFinite方法返回一个布尔值,表示某个值是否为正常的数值。

isFinite(Infinity) // false
isFinite(-Infinity) // false
isFinite(NaN) // false
isFinite(undefined) // false
isFinite(null) // true  
isFinite(-1) // true

①除了Infinity无穷大、-Infinity无穷小、NaN 非法数(非法不正常) undefined 未定义(即有可能是无穷大小)
这几个值会返回false

isFinite对于其他的数值(包括:null空值)都会返回true

四.数据类型的显式转换

1.首先先要分辨出数据类型的值在浏览器的颜色,然后再去测试;

chrome浏览器中 不同类型的值 打印颜色不同

String字符串的颜色是黑色的,

Number数值类型是蓝色的,布尔类型也是蓝色的,

undefined和null类型是灰色的

2.如何显式转换成String字符串类型

  • toString(包装类的方法转) 很常用
    var num = 5;
    console.log(num.toString());  //Boolean也有包装类对象,true/false值也能toString()
  • String(强制转) 很少用
    String()函数存在的意义在于:有些值没有toString(),这个时候可以使用String()。
    比如:undefined和null没有
    
  • (隐式特殊)拼接+ 号来然后拼接字符串方式: 整体就能变为字符串了

    num + " “,(” "空字符串也有意义的,也会分配一个内存给他的,比如var num = " "; 默认值会给undefined )
    当 + 两边其中一个操作符是字符串类型,一个操作符是其它类型的时候,也会先把其它类型转换成字符串再进行字符串拼接,返回字符串.
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-26rnlnfN-1620233715703)(C:\Users\tuyue\AppData\Local\Temp\1615034677240.png)]

3.如何显式转换成Number类型(分整数和浮点数)

  • 推荐Number(); (包装类方法,不智能识别,有严格规范)
    Number()可以把任意值转换成数值,如果要转换的字符串中只要有一个不是数值的字符,返回NaN.
    
    PS:Number()方法不会智能筛选不规范的数值类型,只要不规范全部是NAN非法数.
    但是,更推荐使用,因为不规范的数值你智能筛选出来也是不是原始数据的脏数据了,没有用.
    还不如是规范就规范,不规范就变为NAN.
    
    ①undefined 和 {}空对象 和不规范的数值和字符串 都是 Number转为NAN先.
    ②空数组[] 和  空字符串""   和 null  和 0  和 false   都是Number转为 0先
    ③true=1  和 fasle=0
    
    
<!DOCTYPE html>
<html lang="zh-cn">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>类型转换 number</title>
</head>

<body>
  <script>
    // console.log(parseInt(13.133));//13
    // console.log(parseInt('13.133'));//13
    // console.log(parseInt('13.13u'));//13
    // console.log(parseInt('1k3.13u'));//1

    // console.log(parseInt('0100')); // 100
    // console.log(parseInt('k13')); //NaN

    // console.log(parseFloat(13.133));//13.133
    // console.log(parseFloat('13.133.133'));//13.133 ,只识别规范范围内的小数
    // console.log(parseFloat('13.13u'));//13.13
    // console.log(parseFloat('1k3.13u'));//1

    // console.log(parseFloat('0100')); // 100
    // console.log(parseFloat('k13')); //NaN

    console.log(Number(13.133));//13.133 规范浮点数
    console.log(Number(13));//13         规范整数
    console.log(Number('13.133.133'));//NaN 
    console.log(Number('13.13u'));//NaN
    console.log(Number('1k3.13u'));//NaN
    console.log(Number('0100')); // 100
    console.log(Number('k13')); //NaN


    console.log(~~'33' ); //33   位运算两次反转,即不变
    console.log('33'*1 );  //33  乘1,即也不变
    console.log('33' - 0); // 33 减0 ,即也不变
    console.log('33' + 0); //"330"
    //切记,面对字符串不能+ ,否则同化一定变为字符串


  </script>
</body>

</html>
 // !-[-1,]  数组
    console.log(Number([-1])); //-1
    console.log(Number([1])); //1
    console.log(+[-1]); //-1
    console.log(-[-1]); //1
    console.log(-[-1,]); //1  
    console.log(Number([-1,-2])); //NAN
    console.log(+[-1,-2]);//NAN

这种既不声明也不赋值的变量a,就是使报错的语法.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qgfoMCEb-1620233715708)(C:\Users\tuyue\AppData\Local\Temp\1615104454570.png)]

  • parseInt(智能识别转为int整数,不保留小数位)
    
    var num1 = parseInt("12.3abc");  // 返回12,如果第一个字符是数字会解析知道遇到非数字结束
    var num2 = parseInt("abc123");   // 返回NaN,如果第一个字符不是数字或者符号就返回NaN
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uGtWJitt-1620233715709)(C:\Users\tuyue\AppData\Local\Temp\1615035285109.png)]

  • parseFloat(智能识别转为float浮点数,且保留小数位)
    1.parseFloat()和parseInt转化规则非常相似,不同之处在与
      parseFloat只会解析第一个小数点. 遇到第二个不规范小数点就不识别砍掉了.
    2.如果解析的内容里只有int整数,则和解析成整数parseInt
    3.第一个数字不是数字,就直接NAN.
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lC6RGHpj-1620233715711)(C:\Users\tuyue\AppData\Local\Temp\1615035523863.png)]

  • (隐式特殊)+0,-0等运算 ,不用Number()方法
  • 巧妙直接用"一元加减运算符" 转换为数值类型. 不用Number()方法.
    //原理:一元加+和减-操作符对于非正常数值,会触发Number()转类型,不能乱加有影响
    var str = '500';
    console.log(+'500');		// 字符串加上一元加运算符,变为 取正
    console.log(-'500');		// 字符串加上一元减运算符,变为 取负
    console.log('500' - 0);
    
    //其他一元运算符骚操作,变为数值类型.了解借壳
    console.log(~~'33' ); //33   位运算两次反转,即不变
    console.log('33'*1 );  //33  乘1,即也不变
    console.log('33' - 0); // 33 减0 ,即也不变
    console.log('33' + 0); //"330"
     //切记,面对字符串千万不能使用 +拼接 ,否则一定同化变为字符串
    

4.如何显式转换成Boolean布尔类型

  • ①Boolean()方法.

    死记规则: 除了 “空字符串” / 0 / false / undefined / null / NAN 是false; 消极的都是false
    其他任何的值转换为布尔值 都是 true;

     <script>
       
        console.log(Boolean(1))  //true
        console.log(Boolean(true)) //true
        console.log(Boolean("哈哈")) //true
        console.log(Boolean("123")) //true
        console.log(Boolean(123)) //true
        console.log(Boolean([])) //true
        console.log(Boolean(["x"])) //true
        console.log(Boolean([1])) //true
        console.log(Boolean({})) //true
        console.log(Boolean(" "));  //true  这里不是空字符串了
    
        
    	console.log(Boolean("")) //false   是空字符串
        console.log(Boolean(0)); //false
        console.log(Boolean(false));  //false
        console.log(Boolean(null))  //false
        console.log(Boolean(undefined))  //false
        console.log(Boolean(NaN)); //false
     
    
      </script>
    
    • ②隐式特殊:巧妙直接用"逻辑运算符" 转换为布尔值. 不用Boolean()方法.
      console.log(1);   //1  正常的数值
      console.log(!1);  //false !非逻辑运算符(也是一元运算符)  ,!1结果是false,此处1会转为true
      console.log(!!1); //true  两次取反,就不变,跟两次位运算符~~取反一样,值不变的
      
      

五.数据类型的隐式转换

(即本来是通过上面明显的数据类型的方法函数去转换数据类型,但是通过一个操作符也能让隐式转任何类型,骚操作)

(很难受,即操作符正常使用下你还得额外考虑隐转)

一.如何隐式转化任意类型为number类型:(用+/++和-/-- 一元加和自增运算符)

1.①上述一元运算符会触发Number()方法隐转再加减运算 (从而达到不直接用Number()方法转)
(②isNAN方法也是先会触发Number()方法先,看能否先转为number数值,再去看是否为NAN非法数,是则true))
2.具体规则:
/*一元加和自增运算符的隐式规则其实就和Number函数转化的规则一样:
①undefined 和 {}空对象 和不规范的数值和字符串 都是 Number转为NAN数值先,再去加减
②空数组[] 和  空字符串""   和 null  和 0  和 false   都是Number转为0数值先,再去加减   */
  1. 如果包含的是有效数字字符串或者是有效浮点数字符串,则会将字符串**(通过Number()函数)**转换为数值,再进行加减操作,返回值的类型是:number类型。

  2. 如果不包含有效数字字符串,则number函数会将字符串的值转换为NaN非法数,返回值的类型是:number类型。

  3. 如果是boolean类型,则先会把true或者false隐式转换为1或者0,再进行加减操作,返回值的类型是:number类型。

  4. 如果是null类型,则先会把null隐式转换为0,在进行加减操作,返回值的类型是:number类型。

  5. 如果是undefined,则先会把undefined转换为NaN,再进行加减操作,返回值的类型是:number类型。

  6. 如果是obj对象,则先会通过对象的valueOf()方法,进行转换,如果返回的是NaN非法数,再去调用toString()方法,在进行前面的操作,返回值的类型是:number类型.

3.代码案例:

<script>
    
    // ++x x++ --x x--
    //一元运算符,+ 和++ 都会触发number函数,不规范的数值直接NAN.(null是被当成0)
    var x = "4";
    console.log(+x);   //4
    console.log(++x); // 5
	 //等同  console.log(Number("4")); -> 然后再+/++加减


    x ="4jdj";
    console.log(+x);  //NAN    ,触发number函数,不规范的数值直接NAN
    console.log(++x); //NAN   
	 //等同  console.log(Number("4jdj")); -> 然后再+/++加减


    x = false;
    console.log(+x);   // 0
    console.log(++x);   // 1
    //等同  console.log(Number(false)); -> 然后再+/++加减
    x = true;
    console.log(+x);   // 1
    console.log(++x);   // 2
   //等同  console.log(Number(true)); -> 然后再+/++加减

    x = undefined;
    console.log(+x);   //NaN
    console.log(++x); //NaN  重点 undefined数字运算隐式转换是为NAN的
   //等同  console.log(Number(undefined));//NaN    -> 然后再+/++加减

    x = null;
    console.log(+x);  //0   重点 undefined数字运算隐式转换是为0的
    console.log(-x);  // -0
    console.log(++x);  //1
   //等同  console.log(Number(null));//0    -> 然后再+/++加减


	x=[];  //空数组
    console.log(+x);  //0
    console.log(++x);  //1
   //等同  console.log(Number([])); //0   -> 然后再+/++加减

    x=" "; //空字符串
    console.log(+x);  //0
    console.log(++x);  //1
   //等同  console.log(Number(" "));//0   -> 然后再+/++加减

    x={}; //空obj对象
    console.log(+x);  //NaN
    console.log(++x);  //NaN
   //等同  console.log(Number( {} ));//NaN   -> 然后再+/++加减

  </script>

二.如何隐式转换任意数据类型为Boolean类型 (通过&& || ! !!与或非逻辑运算符)

1.隐式转换布尔类型(不用Boolean()方法达到)

流程控制语句会把后面的值 隐式转换成布尔类型

复习:Boolean布尔类型的隐式转换.
能转换成false的既能转为0: 变为  ""空字符串   0  false  null  undefined  NaN  (有关消极的)
剩下的相反都能转换为true:  变为 "x"非空字符串  非0数字(包括任何负数和整数)  true   任何非空obj对象
//PS:任何非0数值可以隐转转为true布尔类型,但true相反只能转为1 number数值 

console.log(true);  //true
console.log(+true); //1
console.log(-true); //-1
console.log(!10); //false ,10转true
console.log(!-10); //false ,-10转true
console.log(!0); //true , 0转false
if(x=10) // 返回true
if(x=-10) // 返回true
if(x=0) // 返回false 
// 实际最常用的隐式转换布尔类型手段(用! 和 !!,方便直接)?
var a = !'123';  //tfalse , !就是看Boolean的结果取反, 把"123"转为布尔true了,再取反变为布尔false了
var a = !!'123';  //true ,  !!就是看Boolean的结果即可, 把"123"转为布尔true了
2.具体规则:
/*1.具体规则:
    //&&和|| (不常用,结果可能不是布尔,无法确保能转为Boolean)
    //因为都是先拿左边的值去进行布尔类型Boolean函数转换尝试,右边可以不动原值的 
    //再是进行逻辑操作符比较: (余座真饭友 ,  或座真反击) 
    //注意:最后输出是输出原始值的,不是看转换的值,转换值只是我们自己计算时需要而已.
  
  2 !和!! (最常用,结果一定是布尔)
    !都是拿值去进行布尔类型Boolean方法转换尝试,结果取反即可. 
    如果是!!直接就是布尔类型boolean的转换结果了.(自己细品)
 

逻辑操作符一般用于语句判断中。通过判断结果返回的值进行后面的语句操作。

  1. 逻辑非(!)操作符:首先会通过Boolean()函数将其操作值转换为布尔值,然后求反。

  2. 逻辑与(&&)操作符:如果第一个值经过Boolean()函数转换后为true,则返回第二个操作值,否则返回第一个操作值。如果有一个操作值为null这返回null,如果有一个操作值为undefined,则返回undefined,如果有一个值为NaN,则返回NaN。(与座真饭友)

  3. 逻辑或(||)操作符:如果第一个值经过Boolean()函数转换为false,则返回第二个操作值,true则返回第一个操作值。
    (或座真反击)

    (注:逻辑操作符的运算为短路逻辑运算:前一个条件已经能够得出结果后续条件不再执行!)

3.代码案例:
<script>

    String(num)[1] && String(num) || '0' + num;
      //  字符串方法也能,像数组一样用下标取值,没有则返回undefined的.
      //  undefined && '1' || '01'
      // false && '01' || '01'
      // false || '01'
      //'01'
 
    console.log(1 && 2); //2
    //1转为true ,然后&& 输出2

    var x;
    console.log(x && 2); //undefined
    //undefined 先boolean转为false , 然后&& 输出undefined

    
    var y = '0'; 
    console.log(y && 2); //2
    // '0'先boolean转为true,然后&& 输出2

    
    console.log(1 && null); //null
    //1转为true ,然后&& 输出null

    console.log(null && 1); //null
    //null转为false ,然后&& 输出null

    console.log(1 || null); // 1
    //1转为true, 然后|| 输出1

    console.log(null || 1); // 1
    //null转为false ,然后|| 输出1


    //!都是拿值去进行布尔类型Boolean方法转换尝试,结果取反即可. 
    //如果是!!直接就是布尔类型boolean的转换结果了.(自己细品)
    console.log(!!0); //false
    console.log(!!'');  //false
	console.log(!NaN); //true
    console.log(!!NaN);  //false
    console.log(!!undefined);//false
    console.log(!!null); //false
   
  
  </script>

三.关系操作符如何隐式转换 让任意数据类型都能去比较大小:

(这里就不是说隐式去转其他类型,而是注意关系操作符如何比较转化去大小,返回真假了,上面一和二才是实用功能的,能通过+和!!来隐式转number和Boolean,关系运算符会出现各种类型组合的隐式转化问题)

> < >= <= == != 
//尽量用 === 做对比判断 ,不要使用==,因为==隐式很多你不理解的bug
// 1.准确     不会出现因为隐式转换而产生的的乌龙事件 存在风险
// 2.性能原因 动态类型的语言 是语言性能瓶颈之一
    var uid = true;
    console.log(1 === uid); //false (必须类型和值同时相等才行,无法隐式转换)
1.具体规则:(死记,努力往数字number去转换)
  1. 两边全是数值数字,直接按顺序比

  2. 两边全是String数值字符串的,转number直接比即可

  3. 两边都是String文字字符串的,则字符串进行其Unicode编码进行比较。首字符

  4. 如果一个操作值是对象,则调用对象的valueOf()和toString()方法,然后再进行上述都是字符串的unicode比较。

  5. 一边number数值,一边Boolean布尔的,则也是都往number转,再比

  6. 一边String文字或者数字字符串, 一边数字,则都往number转,文字字符会变NAN,直接false

  7. 一边String文字或数字字符串,一边布尔的,则也是都往number转,再比

  8. 遇到NAN比较的,全部都是false ,除非有!取反全是true, !!变回全是false

  9. 在关系运算符!=/==和>=/<=中, null 和 0(包括能转0的)都是对着干的,真假结果颠倒.

    总结: 基本都是努力往数字number去转换即可了
    //尽量用 ===代替 == 做对比判断 
    //===要值和类型都得一样才等, ==只要最后转换的值一样即可,类型不管. 
    //1.准确 不会出现因为隐式转换而产生的的乌龙事件 存在风险
    //2.性能原因 动态类型的语言 是语言性能瓶颈之一
    var uid = true;
    console.log(1 === uid); //false (必须类型和值同时相等才行,无法隐式转换)
3.代码案例:
  <script>
      
     //1.两边全是数值数字,直接按顺序比 
     console.log(3 < 1); // false  ,直接比即可
     console.log(3 < 2 < 1); //true 同级运算符要从左到右运行, 
    //① 3<2 是false
    //② false < 1  是关系运算符隐式转换为0 < 1 
    //③因此最终结果为:true

    //2.两边全是String数值字符串的  
	console.log("3" < "1"); // false  ,转number直接比即可

    //3.两边都是String文字字符串的
    console.log('哈哈哈' == '哈哈哈'); //true
    console.log('哈牙' < '哈哈哈'); //false  
   //两边都是文字字符串,对比unicode编码,首字母牙比第二个哈高,因此false
    //如obj对象比,要用valueof方法转string字符串先再重复上面unicode这一步 
    
   

  	//4.一边数值,一边布尔的,则也是都往number转,再比
    console.log(2 < true); // 2 < 1 => false


    //5.一边String文字或者数字字符串, 一边数字,则都往number转,文字字符会变NAN,直接false
	console.log("哈哈" > 1); //false
	console.log("1" < 1); //false

     //6.一边String文字或数字字符串,一边布尔的,则也是都往number转,再比 
    console.log('0' == false);// true     0 == 0
    console.log('哈哈' == false);// false   NAN==0
	console.log('0u' == false);// false   NAN==0
    
    
    //7.遇到NAN比较的,全部都是false ,除非有!取反全是true, !!变回全是false
    console.log(NaN <= NaN); //fasle NaN和任何值 做任何对比 都是false
    console.log(NaN == 1); //fasle NaN和任何值 做任何对比 都是false
    console.log(NaN != NAN); //true 
    console.log(NaN != 1); //true 

   
   


  </script>
关系运算符一个超级特殊的点:

1.在关系运算符!=/==和>=/<=中, null 和 0(包括能转0的)都是对着干的,真假结果颠倒. 其他正常

2.仅仅在关系运算符==中(!=都不算), null 和 undefined都是对着干的,真假结果颠倒. 其他正常

    //在关系运算符!=/==和>=/<=中 ,黑白颠倒
	console.log(null <= []); //true ,  []要转为0的,对着干了,本来是false
 	console.log(null >= 0); //true ,  本来是false
    console.log(null == 0); //false  ,本来是true的
    console.log(null != 0); //true  ,本来是false的

   //除了!=/==和>=/<= ,在 >和< null和0是正常的
    console.log(null > 0); //false ,在 >和< null和0是正常的
    console.log(null < 0); //false ,在 >和< null和0是正常的

    //然后除了不是0(包括能通过number转0),也都是一切正常的
    console.log(null <= 1); //true , 
    console.log(null == 1); //false   
    console.log(null < 1);  //true
    console.log(null == undefined); // true , 此处0 == NAN会颠倒黑白,本来是false的
    console.log(null != undefined); //false,正常了 
    console.log(null >= undefined); //false,正常了 
    console.log(null <= undefined); //false,正常了 
    console.log(null > undefined); //false,正常了 
    console.log(null < undefined); //false,正常了 
    console.log(undefined >= -1);  // false ,正常了   
    //NAN >= -1

参考原理 : http://bclary.com/log/2004/11/07/#a-11.9.3

  1. 关系运算符 和 相等运算符 并不是一个类别的. 关系>相等的
  2. 关系运算符,在设计上,总是需要运算元尝试转为一个number . 而相等运算符在设计上,则没有这方面的考虑.
  3. 最重要的一点, 不要把 拿 a > b , a == b 的结果 想当然的去和 a >= b 建立联系. 正确的符合最初设计思想的关系是 a > b 与 a >= b是一组 . a == b 和其他相等运算符才是一组. 比如 a === b , a != b, a !== b .
总结:相等操作符== 和 ===的隐式转换规律:
  1. 布尔值、字符串和数值进行比较,会先将其转换为number数值再进行比较。(上案例)
  2. NaN与任何值都不相等,老样子都会返回false。 (上案例)
  3. null和undefined比较是= =相等的true,但不是===全等的false。
console.log(null == undefined); // true   本来是false的,真假颠覆  
 console.log(null === undefined); // false ===不会出现隐式,正常

六.隐式转换大总结: (隐式转obj对象暂时不讲)

一元运算符: +35 -35  ++35 --35
二元运算符: 1+2  2-1
混合使用: 1+-2 -> 1+(-2) //-1
         1+true -> 1+1  //2 true隐式转number数字1
         1+ "true" ->  //"1true"  ,拼接符+让String变boss
1.通常用一元加减符+ -号(注意不是拼接的±二元符), 底层会触发Number函数,来让任何类型隐式转number数值类型
2.通常用! 和 !! ,底层触发Boolean函数,来让任何类型隐式转Boolean布尔类型
3.通常用二元拼接符+号 和 " " 组成: num + " " , 来让任何类型隐式转为String数值类型
4.关系运算符会出现各种类型组合的隐式转化问题,要特别重点复习和深刻记忆的.

**扩展第3点:**在有加+号拼接运算符的公式 ,可以让有String字符串的公式瞬间变绝对优势Boss,即当前+拼接符运算范围内结果一定会是拼接的String字符串,但其他地方字符串就是弱鸡,要字符串通过转number类型.

    console.log('\u0035' + (true * 2) + false);
	// String + (Number) + Boolean  = +加号拼接只要有字符串,则当前+拼接符运算范围结果一定是拼接字符串
    // '5' + 2 => '52' + false
    // '52false'
    console.log('\u0035' + (true * 2) + +false); 
    //让false布尔去隐式转换为0 , 即 "520"  

    console.log('5' - 2 + '3'); // '33'
    // string - number + string
    // '5'- 2 => 3 number
    // 3 + '3' => '33'

   //上面和下面的结果代表,不一定出现"",就代表结果一定是字符串的,看运算范围的

   console.log(' ' + NaN - false + !-1);
    // String + NaN - boolean + boolean
    // ' NaN' - false
    // NaN - 0
    // NaN - 0 -0
    // NaN

七:隐式转换的测试(自己品):

1 + true;
1 + 'true';
1 + undefined;
1 + null;
NaN == NaN;
undefined == null;
null !== undefined;
2 + '5' - 3;
6 > '3' == 3;
undefined == '0';
null == 0;
null >= 0;
parseInt('13.33') === ~~'13.33';
false - 1 <= '0';
'Value is ' + (val != '0') ? 'define' : 'undefine';

海牙老师练手测试:

<script>
    
    console.log('\u0035' + (true * 2) + false);
	// String + (Number) + Boolean  = +加号拼接只要有字符串,则当前+拼接符运算范围结果一定是拼接字符串
    // '5' + 2 => '52' + false
    // '52false'
    console.log('\u0035' + (true * 2) + +false); 
    //让false布尔去隐式转换为0 , 即 "520"  

    console.log('5' - 2 + '3'); // '33'
    // string - number + string
    // '5'- 2 => 3 number
    // 3 + '3' => '33'


    console.log(' ' + NaN - false + !-1);
    // String + NaN - boolean + boolean
    // ' NaN' - false
    // NaN - 0
    // NaN - 0 -0
    // NaN


    console.log(!-[-1,]); //false
    //!-true
    //!-1
    //!true
    //false


    //三目运算符;
     var val = 1;  
     console.log('Value is ' + (val != '0') ? 'define' : 'undefine'); //
   //String + (1!="0")  ? 'define' : 'undefine';
   //String + Boolean  ? 'define' : 'undefine';
   //'Value is true'  ? 'define' : 'undefine';
   //true  ? 'define' : 'undefine'; 
   //'define'


    console.log(false - 1 <= '0'); //true
    //-1 <= "0" 
    //true

     console.log(null >= NaN);  // false
      console.log(NaN >= NaN);  // false
   
 
    
 
  </script>

扩展:Java中obj引用的 toString(无参) 和String.valueOf(有参) 的区别:

Java中obj引用的 toString(无参) 和String.valueOf(有参) 的区别:

String str1 = obj引用.toString(); VS String str1 = String类.valueOf(obj对象/int基类);
toString(无参)valueOf(有参)的区别就是;

1、大体讲:
①valueOf底层其实就是toString(无参/有参),能变"基本类型""obj对象"为String形式。
②而toString(无参)是只让obj对象变为字符串形式输出的方法)
③而valueOf(有参)实际包含着一部分的toString(无参)方法。
④共同点作用:都有一个相同的功能那就是可以把对象,转换和返回成String字符串形式输出
2、细致讲:
①一个无参数(内部的return转),实例方法要new对象,仅仅是改变对象自身输出形式的方法(里面是可以自己手写改对象的输出形式,但一定要字符串形式);
②一个有参数(直接形参外部转),静态方法用类调,将特定的“参数”转为字符串String,其实底层也是会去调"基类的包装类或者obj对象“重写的toString(/有参)方法.
③因此综上:String.valueOf()有着独特优点:就是还可以把"基本类型"转换字符串String,而toString(无参)不能。



PS注意1:通过方法转型如果obj为null不会抛出NullPointerException异常;
而是将obj对象转换成"null"字符串。这样 str1 就被赋值为 "null",
这样乍一看没什么问题,感觉这样可以避免NullPointerException异常,如果后期要对str1要做其他类型的转换就会出问题。
比如:Integer.valueOf(str1);这是就会报错NumberFormatException提示数据类型转换出错(因为返回的字符串“null”无法转去Integer)。
到这里就会发现 String.valueOf()埋下的坑了。
所以一般情况下在使用这两个方法前最后都要考虑一下null值得情况,不然后期发现问题,改数据将是非常痛苦的。


PS注意2**jdk里String.valueOf(Object/int i)源码如下:(底层是toString(有参/有参))
①  public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); }  
//底层是toString(无参),调obj对象的toString(无参)方法(自定义类对象的话记得要自己重写toString)public static String valueOf(int i) {  return Integer.toString(i);} 
 //底层是toString(有参),调基数的包装类的toString(有参)方法(不需要重写) 
 
③而Object的toString()源码如下:
     public String toString() {   //仅仅只能是对象
        return getClass().getName() + '@' + Integer.toHexString(hashCode());
    }



 PS注意3:这种方法套方法的套路:其实是一样的不要怕!
//正常写法:
    Customer customer = new Customer();
    String s =  String.valueOf(customer);
    System.out.println(s); 
    //这里valueOf(customer)底层一样会调customer的toString无参方法,和下面是一样的
    System.out.println(customer); //这里和上面其实也一样,底层一样是调用customer的toString方法,是同一样的结果,只是一个静态一个实例
    
 //方法套方法写法:
public String toString() {  //把对象以字符串的形式输出;
        return String.valueOf(11); // 这里底层就是再去调一次Integer包装类的
        //toString(有参)转为字符串,返回即可。其实没变,也可以直接手打"id = " + id;
    }   

public String toString() {  //把对象以字符串的形式输出;
        return String.valueOf(new Vip(11)); 
        //这回会报错, Exception in thread "main" java.lang.StackOverflowError
        //因为String.valueOf(new Vip(11))实际底层会去调toString无参,即这个上面这个重写的public String toString()方法
        //那么就会进入递归,如果没有条件限制,就会死循环栈溢出报错。
    }       

mberFormatException提示数据类型转换出错(因为返回的字符串“null”无法转去Integer)。
到这里就会发现 String.valueOf()埋下的坑了。
所以一般情况下在使用这两个方法前最后都要考虑一下null值得情况,不然后期发现问题,改数据将是非常痛苦的。

PS注意2:**jdk里String.valueOf(Object/int i)源码如下:(底层是toString(有参/有参))
① public static String valueOf(Object obj) { return (obj == null) ? “null” : obj.toString(); }
//底层是toString(无参),调obj对象的toString(无参)方法(自定义类对象的话记得要自己重写toString)
②public static String valueOf(int i) { return Integer.toString(i);}
//底层是toString(有参),调基数的包装类的toString(有参)方法(不需要重写)

③而Object的toString()源码如下:
public String toString() { //仅仅只能是对象
return getClass().getName() + ‘@’ + Integer.toHexString(hashCode());
}

PS注意3:这种方法套方法的套路:其实是一样的不要怕!
//正常写法:
Customer customer = new Customer();
String s = String.valueOf(customer);
System.out.println(s);
//这里valueOf(customer)底层一样会调customer的toString无参方法,和下面是一样的
System.out.println(customer); //这里和上面其实也一样,底层一样是调用customer的toString方法,是同一样的结果,只是一个静态一个实例

//方法套方法写法:
public String toString() { //把对象以字符串的形式输出;
return String.valueOf(11); // 这里底层就是再去调一次Integer包装类的
//toString(有参)转为字符串,返回即可。其实没变,也可以直接手打"id = " + id;
}

public String toString() { //把对象以字符串的形式输出;
return String.valueOf(new Vip(11));
//这回会报错, Exception in thread “main” java.lang.StackOverflowError
//因为String.valueOf(new Vip(11))实际底层会去调toString无参,即这个上面这个重写的public String toString()方法
//那么就会进入递归,如果没有条件限制,就会死循环栈溢出报错。
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值