【数据结构】浅识泛型

news2024/11/13 10:40:56

目录

1、包装类

1.1、基本数据类型和其包装类

1.2、装箱和拆箱 

1.2.1、装箱

 1.2.2、拆箱

1.2.3、面试题 

2、泛型的概念

3、引出泛型

3.1、语法

4、泛型类的使用 

4.1、语法

5、裸类型(Raw Type)

6、泛型是如何编译的

6.1、擦除机制

 6.2、不能实例化泛型类型数组

7、泛型的上界

7.1、语法

 7.2、复杂示例

8、泛型方法

8.1、语法定义

9、强制类型转换数组和数组元素


1、包装类

在Java当中,由于基本类型不是继承自Object为了在泛型代码中可以支持基本类型,Java给每个基本类型都对应了一个包装类型。

1.1、基本数据类型和其包装类

基本数据类型包装类
byteByte
shortShort
intinteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

✨总结:八种基本数据类型所对应的包装类,除了integer和Character,其余基本类型的包装类都是首字母大写。

 举例:当在泛型代码中使用时

import java.util.LinkedList;

public class Test {
    public static void main(String[] args) {
// String类型继承自Object,可以在泛型代码中使用
        LinkedList<String > linkedList = new LinkedList<>();
        linkedList.add("hello");
    }
}

基本数据类型(不继承于Object的数据类型,都不能直接出现在泛型代码的<>当中) 

🔅 修改:将基本数据类型修改为其所对应的类类型(包装类)。

1.2、装箱和拆箱 

装箱把基本数据类型变为对应的包装类型
拆箱将引用数据类型拆箱为基本数据类型

1.2.1、装箱

public class Test {
    public static void main(String[] args) {
        int a = 10;
        Integer val1 = a;//自动装箱
        //因为Integer是一个类,所以它可以直接调用他的方法或者new一个对象用来装箱
        Integer val2 = Integer.valueOf(a);//显示装箱
        Integer val3 = new Integer(a);//显示装箱
        System.out.println(val1);
    }
}

 对变量val1进行反汇编,来查看自动装箱的过程。

 1.2.2、拆箱

📕自动拆箱

public class Test {
   public static void main(String[] args) {
        Integer val1 = 10;
        int a = val1;//自动拆箱
        System.out.println(a);
    }
}

对上述代码进行反汇编,查看自动拆箱的过程。

📕 显示拆箱

通过上述的反汇编,可以看见拆箱的时候会调用了一些方法,那么在编译过程中,将反汇编中调用的方法直接调用,这样的写法就是显示拆箱

public class Test {
    public static void main(String[] args) {
        Integer val1 = 10;
        int b = val1.intValue();//显示拆箱
        System.out.println(b);
    }
}

以Integer包装类为例,类当中有很多装箱和拆箱的方法,那么是不是想要什么类型的数据,就可以拆成什么类型的数据?

答案当然是可以。

public class Test {
    public static void main(String[] args) {
        Integer val1 = 10;
        double d = val1.doubleValue();
        System.out.println(d);
        short t = val1.shortValue();
        System.out.println(t);
    }
}

📗Integer类当中的拆箱方法 

1.2.3、面试题 

下列代码输出的结果是

public class Test {
    public static void main(String[] args) {
        Integer a = 100;
        Integer b = 100;
        System.out.println(a == b);
    }
}

结果为

但是当a 和 b 改为200,就会报错。

 上述代码设计到了装箱的代码,装箱会调用Integer类的valueOf方法,那么来看一下这个代码

  • 当两个变量值为100,小于127,在缓存数组cache当中同一位置取值,用==比较大小,返回结果为true
  • 当两个变量值为200,大于127,在缓存数组cache当中找不到该数字,那么就会返回new 的新的地址。
  • 用==比较,比较的是两个数据的存储位置。所以返回false。

❗❗❗【注意事项】

当装箱之后,数据类型,就会变为相应的引用数据类型,引用数据类型比较的时候,使用==

表示的是:比较两个数据存储的位置 


2、泛型的概念

一般的类和方法,只能使用具体的类型;要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。

泛型是在JDK1.5引入的新语法,通俗讲,泛型:就是适用于许多类型。从代码上将,就是对类实现了参数化。

3、引出泛型

实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据放法返回数组中某个下标的值?

思考:

  • 之前学过的数组,只能指定存放指定的元素,例如:int[ ] array = new int[12];String[ ]  strs = new String[12];
  • 所有类的父类,默认都是Object类。数组是否可以创建为Object?

代码示例:按照上述说法,实现了一个类,包含一个数组成员可以存放任何类型的数据,也可以根据方法返回数组中某个下标的值

 当我们知道数组2下标处是double类型的数据,通过这种方式获取数据,编译器报错,这是什么原因呢?

直接原因就是,接收类型和返回值类型不匹配,导致这里出错。说到这里就有人说,向下转型(强转)或者直接用Object类型的变量来接收返回值,不就解决问题了吗?

//方法一:强转(向下转型)
double d = (double)myArray.getPos(2);
//这样接收数据的好处就是得到的数据,由于数据类型固定,可以在接下来的代码中直接参与运算

//方法二:用Object类型的变量来接收
Object d = myArray.getPos(2);
//这样接收数据的好处是,不用管他是那个位置的数据,都可以直接接收;但是缺点就是,得到的数据不能直接参与运算

虽说这两种方法暂时解决了编译器报错的问题,但是又产生了新的问题

  • 方法一:现在作为例子的代码只用三个元素,我们想要某个位置的数据的时候,可以知道这个数据是什么类型的数据,可以通过强转来解决这个问题,但是在以后写大型代码的时候,以变量的形式存入数据,数据有成百上千的时候,那个时候我们要获取某个位置的数据的时候,还要像现在一样,去查那个数据是什么类型的数据,再进行强转吗,这样写代码的效率太低了。
  • 方法二:这样写,有掩耳盗铃的意味,在代码当中,得到这个数据,就是为了在接下来的操作中能够使用,但是得到的这个数据,并不能直接在接下来的代码当中使用,用来接收的变量的类型是Object,那么这个变量的类型可以是String,也可以是Char,没有办法确定具体的类型,那么就不可能参与到后续的程序中。

 通过观察上述代码就产生了两个问题:

  1. 存放数据的时候,任何类型的数据都可以存放
  2. 2号下标的元素本身就是double类型的数据,但是用double类型的变量接收,编译器报错。必须得强转
  •   在以Object为数组类型的情况下,虽然可以什么类型都可以存放,但是更多的情况下,我们还是希望指定他只能存放一种数据类型。而不是同时持有那么多的类型。所以,这里就要说到泛型。
  • 泛型的只要目的就是指定当前的容器,要持有什么类型的对象。让编译器去检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。 

3.1、语法

class 泛型类名称<类型形参列表>{
    //这里可以使用类型参数
}

//举例:
class MyArray<T,E,O,N,...>{
}

class 泛型类名称<类型形参列表> extends 继承类 /*这里可以使用类型参数*/{
    //这里可以使用类型参数
}

//举例
class ClassName<T1,T2,....Tn> extends ParentClass<T1>{
    //可以使用部分类型参数
}

那么上述的代码就可以这样修改

 在实例化对象的时候,指定了泛型类的指定参数类型是Interger。所以在编译的时候,写的其他类型的数据,通过编译器检测会报错。

❗❗❗提示:在示例话对象的时候,也可以这样写

当编译器可以根据上下文推导出类型实参时,可以省略实参的填写

MyArray<Integer> myArray = new MyArray<>();
//在后面new的时候,MyArray后面的<>中的内容可以省略

❗❗❗ 注意:

在上述的代码中,有这样一句代码。

public T[] obj = (T[])new Object[3];

这句代码是错的,这样写只是让编译器不会报错。

❗❗❗总结:

  • 类名后的<T>代表占位符,表示当前类是一个泛型类。                                                        
  • 不能new泛型类型的数组
    T[] ts = new T[5];//写法是错误的
  • 在实例化对象的时候,添加<Integer>表示指定当前类型
  MyArray<Integer> myArray = new MyArray<>();
  • 在接收读取到数组中某个元素的时候,不需要再进行强制类型转换。
  • 当在实例化时,指定当前泛型类的指定参数类型是Integer,在数组中写入其他类型的参数时,编译器就会报错。


4、泛型类的使用 

4.1、语法

泛型类<参数类型> 变量名; //定义一个泛型类引用
new  泛型类<类型实参>(构造方法实参); // 示例化一个泛型类对象

示例:

 MyArray<Integer> a;
 MyArray<Integer> myArray = new MyArray<>();

注意:泛型只能接收类,所有的基本数据类型必须使用包装类!!


5、裸类型(Raw Type)

裸类型是一个泛型类但是没有带着类型实参,这样写,示例化类型对象当中的数组,又可以存放各种类型的元素了

 在实例化对象的时候,当前泛型类没有指定参数类型,在理论上,编译器会报错,但是从这里看,编译器并没有报错。

❗❗❗注意:

我们不要自己去使用裸类型,裸类型是为了兼容老版本的API保留的机制。

❗❗❗总结:

  • 泛型是将数据类型参数化,进行传递
  • 使用<T>表示当前类是一个泛型类。
  • 泛型目前为止的优点:数据类型参数化,编译时自动进行类型检查和转换 

 


6、泛型是如何编译的

6.1、擦除机制

泛型类(MyArray)源文件在通过编译之后生成字节码文件,字节码文件在JVM上运行,最后生成结果。

我们可以通过命令:javap -c 来查看字节码文件。

被圈出来的部分在MyArray类当中

 

 在编译的过程中,将所有的T替换为Object。这种机制被称为:擦除机制

泛型是编译期间的一种机制,在运行的时候没有泛型的概念!!!

因为字节码文件是在JVM上运行的,也就是说,JVM没有泛型的概念。

 编译的时候就执行了两件事情:编译时自动进行类型检查和转换,编译完成之后就没有泛型了,运行的时候都是Object。

❗❕那么到这里,又产生了一个问题,像下面的代码,在编译完成之后T不是会被擦除为Object吗?为什么还会报错?

 这里就涉及到了更深层次的知识,我们只看最终结论就行。

  • 在定义泛型数组的时候,我们可以这样写。

对数组的元素进行强制类型转换

在MyArray数组实例化的的同时规定了MyArray类的类型,

❗❗❗在int a = myArray.getPos(1);这句代码中getPos方法返回的是T类型的数据,但是在用int类型的变量来接收的时候,泛型的优点就在这里体现,会自动进行类型检查。当数组是Integer类型的时候,那么用int类型和Integer类型都能接收。

❗❗❗ Java官方在写的时候也是这种思想,以ArrayList为例,他的每个数组都是Object类型的。

 在来看ArrayList的get方法

 

 ❗❗❗总结:

  • 今后我们在定义泛型数组的时候,正确的写法是,下面这种样子。

 

  •  像这样的写法不是正确的,他只是让编译器不报错。这样写会有很大的弊端。

 

 6.2、不能实例化泛型类型数组

  • 不能对数组的类型进行强制类型转换
class MyArray1<E>{
    public E[] obj = (E[])new Object[3];//泛型类型的数组在示例化的时候,已经
//定义好了是object类型,就不能再强转了。在实例化类的时候,将类指定的类型,传递
//上来,E表示的就是Integer类型。 
    public E[] getArray(){
        return obj;
    }

    public void setObj(int pos,E val){
        obj[pos] = val;
    }
}

public class Test {
    public static void main(String[] args) {
        MyArray1<Integer> myArray1 = new MyArray1<>();
        myArray1.setObj(0,10);
        myArray1.setObj(1,71);
        Integer[] integers = myArray1.getArray();
    }

❓❓❓ 这里为什么会报类型转换异常?

  • 原因在于定义数组的时候E[] obj = (E[])new Object[3];new的是Object类型的数组,在前面不能再强制类型转换了,数组在开辟空间的时候,已经定义好了类型,那么数组类型就不能改变,只能改变数组当中元素的类型。

❗【举例说明】

  • 定义一个int类型的数组,数组空间开辟完成之后,将数组类型转换为short类型,那么该数组的空间大小该怎样计算?

🔆🔆来看调试的结果

数组的类型并没有被强转 

那么通过强制类型转换之后,来看结果。

编译器还是会报相同的错误。

  • 这就是这种写法的弊端,泛型类当中的数组是Object类型的,那么数组当中的元素,可以是任意类型的,可以是Integer类型的,也可以是Char类型的,也可以是Double类型。
  • 当采用上述的强制类型转换(向下转型),编译器还是会报错,编译器认为数组这样强转是不安全的。
  • 当在定义数组的时候 ,不确定是数组的类型是什么的时候,可以使用下列的方法来写(采用反射的手段来解决)

❗❗❗正确的方式:通过反射创建 ,指定数组类型

import java.lang.reflect.Array;

class MyArray2<E>{
    public E[] obj ;
    //创建一个构造方法
    public MyArray2(Class<E> clazz, int capacity) {
        obj = (E[])Array.newInstance(clazz, capacity);
     //这里代表的意思是:指定类型的数组,指定new一个什么类型的数组,容量是多大
    }
    public E[] getArray(){
        return obj;
    }

    public void setObj(int pos,E val){
        obj[pos] = val;
    }
}
public class Test {
    public static void main(String[] args) {
        MyArray2<Integer> myArray2 = new MyArray2<>(Integer.class,10);
        //这里就相当于我已经指定了数组的类型是Integer
        myArray2.setObj(0,10);
        myArray2.setObj(1,71);
        Integer[] integers = (Integer[])myArray2.getArray();

    }

 

❗❗❗总结:

  • 数组的类型在new的时候已经确定,就不能强制类型转换数组的类型,但是可以修改数组的元素类型。
  • 数组类型不确定的时候,可以使用反射来创建指定数组的类型

7、泛型的上界

在定义泛型类时,有时候需要对传入的类型变量做一定的约束,可以通过类型边界类约束。

7.1、语法

class 泛型类名称<类型形参 extends 类型边界>{
    .....
}

//举例
public class MyArray<E extends Number>{
    ...
}

❗❗❗注意:<E extends number>是泛型的上界,他代表:E是Number的子类或者E是Number本身

抽象类Number的直接子类 

 

 7.2、复杂示例

class Alg<E extends Comparable<E>>{
    ...
}

这个示例当中的代码,代表将来指定的参数类型,一定实现了这个接口。

代码示例:找数组中的最大值。

class Alg<E extends Comparable<E>>{
    public E findMax(E[] array){
        E max = array[0];
        for(int i = 1;i < array.length;i++){
            if(max.compareTo(array[i])<0){
                //比较的是引用类型,所以不能直接用<  >  =比较
                max = array[i];
            }
        }
        return max;
    }
}
public class Test {
    public static void main1(String[] args) {
        Alg<Integer> alg = new Alg<>();
        Integer[] array = {1,2,3,4,10,79,25,36};
        Integer val =  alg.findMax(array);
        System.out.println(val);
    }
}

 


8、泛型方法

8.1、语法定义

方法限定符<类型形参列表> 返回值类型  方法名称(形参列表){
    ...
}

示例:还是上述代码,找数组中的最大值

class Alg2{
    public<E extends Comparable<E>> E findMax(E[] array){
        //相当于给这个方法指定参数类型为E,并实现Comparable接口,给这个方法做一定的约束
        E max = array[0];
        for(int i = 1;i < array.length;i++){
            if(max.compareTo(array[i])<0){
                //实现类Comparable,调用CompareTo方法,进行元素比较
                max = array[i];
            }
        }
        return max;
    }
}
public class Test {
    public static void main1(String[] args) {
        Alg2 alg2 = new Alg2();
        Integer[] array = {1,2,3,4,10,79,25,36};
        Integer val =  alg2.findMax(array);
        System.out.println(val);
    }
}

❓❓那么这里就有一个疑问,从哪里传给findMax方法类型的参数呢?

是从这里

 画出来的地方是可以省略的,它可以从findMax方法的参数中去反推,传给E的是Integer类型。

❓上述的写法有些麻烦,每次调用findMax方法的时候,都要实例化该类,能不能有简单一点的方法?

当然是有的

  • 在类当中写一个静态方法,调用的时候直接使用类名来调用,不用再实例化Alg3对象。
class Alg3{
    public static<E extends Comparable<E>> E findMax(E[] array){
        E max = array[0];
        for(int i = 1;i < array.length;i++){
            if(max.compareTo(array[i])<0){
                max = array[i];
            }
        }
        return max;
    }
}
public class Test {
    public static void main(String[] args) {
        Integer[] array = {1,2,3,4,10,79,25,36};
        Integer val =  Alg3.findMax(array);
        System.out.println(val);
    }

9、强制类型转换数组和数组元素

在这里再次强调一下,强制类型转换数组类型和数组元素的类型。

  • 当实例化数组的时候,数组的类型已经确定,那么数组类型再什么情况下,都不能再强转为其他类型。
  • 当创建泛型类的时候,实例化了数组,数组的类型已经固定,想要改变数组的元素的类型,可以通过在泛型类当中定义一个set方法,来修改数组元素的类型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/182782.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Springboot+ssm371的在线考试系统maven idea

摘 要 I 1 绪论 1 1.1研究背景 1 1.2研究现状 1 1.3研究内容 2 2 系统关键技术 3 springboot是基于spring的快速开发框架, 相比于原生的spring而言, 它通过大量的java config来避免了大量的xml文件, 只需要简单的生成器便能生成一个可以运行的javaweb项目, 是…

DPO4104示波器

18320918653 DPO4104 详细说明&#xff1a; 美国泰克Tektronix DPO4104数字荧光示波器主要产品特色&#xff1a;Inspector智能存储管理2.串行触发和分析3.10.4”更大的显示器, 前面板上USB和CompactFlash端口, 及TekVPI?改善的探头接口, 更强的操作渐 变性商品名称 &#x…

针孔相机模型

针孔相机模型坐标系(1) 图像像素坐标系(2) 图像物理坐标系(3) 相机坐标系(4) 归一化平面坐标系(5) 世界坐标系畸变校正针孔相机模型中一般会涉及到图像像素坐标系、图像物理坐标系、相机坐标系、归一化平面坐标系和世界坐标系这5个坐标系。 坐标系 (1) 图像像素坐标系 图像像…

IDEA设置界面和控制台的滚动条颜色

前言 不知道大家是否和我一样有这么一个烦恼&#xff1a; IDEA自带的滚动条颜色很暗&#xff0c;配上一些主题颜色搭配很难发现。 所以今天就想着怎么可以修改滚动条颜色&#xff0c;首先去网上搜了搜都是什么鼠标滚轮加shift滚动&#xff0c;一点也不实用 偶然看到了个不错的…

图表控件LightningChart.NET 系列教程(七):LightningChart 组件——LightningChart.NET 函数库

LightningChart.NET SDK 是一款高性能数据可视化插件工具&#xff0c;由数据可视化软件组件和工具类组成&#xff0c;可支持基于 Windows 的用户界面框架&#xff08;Windows Presentation Foundation&#xff09;、Windows 通用应用平台&#xff08;Universal Windows Platfor…

匿名函数 lambda

匿名函数 lambda 匿名函数&#xff1a;一句话函数&#xff0c;比较简单的函数,没有函数名的函数 在Python中&#xff0c;lambda的语法是唯一的 lamlambda a,b:ab lamlam(a1,b2) # 传参 print(lam) # 3lmbda的语法是唯一的。其形式如下&#xff1a;lambda argument_list: expr…

python图像处理(prewitt算子)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 前面几章谈到了灰化、增强、旋转、滤波等内容,今天来谈一谈边缘检测。边缘检测是图像处理的重要内容。很多图像分割、图像识别的前一步就是边缘检测。某种意义上说,边缘检测的好坏…

7-查看和处理文件内容

7-查看和处理文件内容 文本文件 ASCII、UTF-8、Unicode、ANSItxt、xml、conf、properties、yml等配置文件、日志文件、源代码 二进制文件 可执行文件、图片、音频、视频 cat 全拼&#xff1a;concatenate [kənˈkt(ə)nˌeɪt] 连接 格式&#xff1a;cat 文件名 more/…

2. Spring 注解开发

文章目录1. 用注解开发定义bean2. 纯注解开发3. 注解开发的 bean 管理3.1 作用范围管理&#xff08;单例或非单例&#xff09;3.2 生命周期管理4. 注解开发的依赖注入4.1 引用类型的依赖注入4.2 简单类型的依赖注入4.2.1 直接注入值4.2.2 注入 properties 文件中的值5. 注解开发…

Acwing---1101. 献给阿尔吉侬的花束

献给阿尔吉侬的花束1.题目2.基本思想3.代码实现1.题目 阿尔吉侬是一只聪明又慵懒的小白鼠&#xff0c;它最擅长的就是走各种各样的迷宫。 今天它要挑战一个非常大的迷宫&#xff0c;研究员们为了鼓励阿尔吉侬尽快到达终点&#xff0c;就在终点放了一块阿尔吉侬最喜欢的奶酪。…

MYSQL不存在插入 存在更新的解决方法和对比

设置主键id自增&#xff0c;name为唯一索引 一、避免重复插入 insert ignore into&#xff08;有唯一索引&#xff09; 关键字/句: insert ignore into&#xff0c;如果插入的数据会导致 UNIQUE索引 或 PRIMARY KEY 发生冲突/重复&#xff0c;则忽略此次操作/不插入数据&…

Leetcode.1664 生成平衡数组的方案数

题目链接 Leetcode.1664 生成平衡数组的方案数 题目描述 给你一个整数数组 nums。你需要选择 恰好 一个下标&#xff08;下标从 0 开始&#xff09;并删除对应的元素。请注意剩下元素的下标可能会因为删除操作而发生改变。 比方说&#xff0c;如果 nums[6,1,7,4,1]nums [6,1…

spark转化操作

文章目录转化操作Transformer算子概念单RDD转换函数多RDD转换函数map与flatmap转化操作 由于spark的惰性计算特性&#xff0c;RDD只有在第一次行动操作中被用到时才会真正进行计算&#xff0c;因此我打算将文章内容分为"转化操作"和"行动操作"两部分&…

【web】微信小程序笔记小结(视图与逻辑)

过完年回来干正事了orz 来源&#xff1a;黑马程序员前端微信小程序开发教程 目录 I. 页面导航 ① 概念 ② 导航方式 1&#xff09;声明式导航 ※※ 导航到 tabBar 页面 ※※ 导航到非 tabBar 页面 ※※ 后退导航 2&#xff09;编程式导航 ※※ 导航到 tabBar 页面…

Nature立新规:ChatGPT等大模型不可以成为作者

众所周知&#xff0c;AI 的超参数决定着模型学习效果和速度。相比普通机器学习任务&#xff0c;深度学习需要的训练时间较长&#xff0c;因此调参技巧就显得尤为重要。 但鉴于深度学习「炼丹」的特性&#xff0c;不同的模型需要不同的超参数&#xff0c;而每个超参的意义又不同…

【头歌】汉诺塔(Hanoi)的递归算法

任务描述本关任务&#xff1a;汉诺塔(Hanoi)的递归算法。相关知识相传在古印度圣庙中&#xff0c;有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上&#xff0c;有三根杆(编号A、B、C)&#xff0c;在A杆自下而上、由大到小按顺序放置64个金盘(如下图)。游戏的目标&a…

C语言中数组变量作为函数参数传值的两种方式:数组类型 指针类型 以及“C语言中数组变量(名)的本质是指针变量”

文章目录Intro & SummaryCode & Output运行截图Code关于数组长度在被调函数中的计算错误运行截图 & 警告信息Code数组变量是一类特殊的、指向自己的指针变量Intro & Summary 我在 main 函数中定义了一个数组&#xff0c;要将该数组作为参数传递给其他方法。那…

Lesson 4.3 梯度下降(Gradient Descent)基本原理与手动实现

文章目录一、梯度下降基本原理与学习率1. 数据背景与最小二乘法求解2. 一维梯度下降基本流程2.1 参数移动第一步2.2 梯度下降的多轮迭代3. 梯度下降算法特性与学习率二、梯度下降一般建模流程与多维梯度下降1. 多维梯度下降与损失函数可视化2. 梯度下降计算流程3. 二维梯度下降…

jvm学习的核心(四)---执行引擎和字符串

知识点总结于b站宋红康老师&#xff0c;视频链接 文章目录1.执行引擎1.1.执行引擎概述1.2.执行引擎的工作流程1.3.jvm的解释器和即时编译器&#xff08;JIT&#xff09;1.3.1.解释器&#xff0c;即时编译器概述1.3.2.常见即时编译器1.3.3.热点代码探测1.String Table1.1 string…

Go语言基础入门第三章

常量 常量是一个简单值的标识符&#xff0c;在程序运行时&#xff0c;不会被修改的量。 常量中的数据类型只可以是布尔型、数字型&#xff08;整数型、浮点型和复数&#xff09;和字符串型。 const identifier [type] value可以省略类型说明符[type]&#xff0c;因为编译器…