阿里架构师的Java总结篇系列——Java泛型

Java 泛型中的通配符详解 可以使用上界通配符来放宽对变量的限制。例如,你想编写一个方法,该方法适用于List, List 和 List;就可以通过使用上界通配符来实现这一点。声明一个上界通配符,需要使用通配符 ('?'),跟上 extends 关键字,然后再跟它的上界。比如,编写用于 Number 列表和 Number 子类型(如 Integer、Double 和 Float)的方法,可以指定 List 阅读详情

一. 泛型概念的提出(为什么需要泛型)?

首先,我们看下下面这段简短的代码:

public class GenericTest {
	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("qqyumidi");
		list.add("corn");
		list.add(100);
		for (int i = 0; i < list.size(); i++) {
			String name = (String) list.get(i);
			// 1
			System.out.println("name:" + name);
		}
	}
}

定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他编码原因,很容易出现类似于//1中的错误。因为编译阶段正常,而运行时会出现“java.lang.ClassCastException”异常。因此,导致此类错误编码过程中不易发现。

在如上的编码过程中,我们发现主要存在两个问题:

  1. 当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。
  2. 因此,//1处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现“java.lang.ClassCastException”异常。

那么有没有什么办法可以使集合能够记住集合内元素各类型,且能够达到只要编译时不出现问题,运行时就不会出现“java.lang.ClassCastException”异常呢?答案就是使用泛型。

二.什么是泛型?

泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

看着好像有点复杂,首先我们看下上面那个例子采用泛型的写法。

public class GenericTest {
	public static void main(String[] args) {
		/*
        List list = new ArrayList();
        list.add("qqyumidi");
        list.add("corn");
        list.add(100);
        */
		List<String> list = new ArrayList<String>();
		list.add("qqyumidi");
		list.add("corn");
		//list.add(100);   // 1  提示编译错误
		for (int i = 0; i < list.size(); i++) {
			String name = list.get(i);
			// 2
			System.out.println("name:" + name);
		}
	}
}

采用泛型写法后,在//1处想加入一个Integer类型的对象时会出现编译错误,通过List,直接限定了list集合中只能含有String类型的元素,从而在//2处无须进行强制类型转换,因为此时,集合能够记住元素的类型信息,编译器已经能够确认它是String类型了。

结合上面的泛型定义,我们知道在List中,String是类型实参,也就是说,相应的List接口中肯定含有类型形参。且get()方法的返回结果也直接是此形参类型(也就是对应的传入的类型实参)。下面就来看看List接口的的具体定义:

public interface List<E> extends Collection<E> {
	int size();
	Boolean isEmpty();
	Boolean contains(Object o);
	Iterator<E> iterator();
	Object[] toArray();
	<T> T[] toArray(T[] a);
	Boolean add(E e);
	Boolean remove(Object o);
	Boolean containsAll(Collection<?> c);
	Boolean addAll(Collection<? extends E> c);
	Boolean addAll(int index, Collection<? extends E> c);
	Boolean removeAll(Collection<?> c);
	Boolean retainAll(Collection<?> c);
	void clear();
	Boolean equals(Object o);
	int hashCode();
	E get(int index);
	E set(int index, E element);
	void add(int index, E element);
	E remove(int index);
	int indexOf(Object o);
	int lastIndexOf(Object o);
	ListIterator<E> listIterator();
	ListIterator<E> listIterator(int index);
	List<E> subList(int fromIndex, int toIndex);
}

我们可以看到,在List接口中采用泛型化定义之后,中的E表示类型形参,可以接收具体的类型实参,并且此接口定义中,凡是出现E的地方均表示相同的接受自外部的类型实参。

自然的,ArrayList作为List接口的实现类,其定义形式是:

public class ArrayList<E> extends AbstractList<E> 
       implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
	public Boolean add(E e) {
		ensureCapacityInternal(size + 1);
		// Increments modCount!!
		elementData[size++] = e;
		return true;
	}
	public E get(int index) {
		rangeCheck(index);
		checkForComodification();
		return ArrayList.this.elementData(offset + index);
	}
	//...省略掉其他具体的定义过程
}

由此,我们从源代码角度明白了为什么//1处加入Integer类型对象编译错误,且//2处get()到的类型直接就是String类型了。

三.自定义泛型接口、泛型类和泛型方法

从上面的内容中,大家已经明白了泛型的具体运作过程。也知道了接口、类和方法也都可以使用泛型去定义,以及相应的使用。是的,在具体使用时,可以分为泛型接口、泛型类和泛型方法。

自定义泛型接口、泛型类和泛型方法与上述Java源码中的List、ArrayList类似。如下,我们看一个最简单的泛型类和方法定义:

public class GenericTest {
	public static void main(String[] args) {
		Box<String> name = new Box<String>("corn");
		System.out.println("name:" + name.getData());
	}
}
class Box<T> {
	private T data;
	public Box() {
	}
	public Box(T data) {
		this.data = data;
	}
	public T getData() {
		return data;
	}
}

在泛型接口、泛型类和泛型方法的定义过程中,我们常见的如T、E、K、V等形式的参数常用于表示泛型形参,由于接收来自外部使用时候传入的类型实参。那么对于不同传入的类型实参,生成的相应对象实例的类型是不是一样的呢?

public class GenericTest {
	public static void main(String[] args) {
		Box<String> name = new Box<String>("corn");
		Box<Integer> age = new Box<Integer>(712);
		System.out.println("name class:" + name.getClass());
		// com.qqyumidi.Box
		System.out.println("age class:" + age.getClass());
		// com.qqyumidi.Box
		System.out.println(name.getClass() == age.getClass());
		// true
	}
}

由此,我们发现,在使用泛型类时,虽然传入了不同的泛型实参,但并没有真正意义上生成不同的类型,传入不同泛型实参的泛型类在内存上只有一个,即还是原来的最基本的类型(本实例中为Box),当然,在逻辑上我们可以理解成多个不同的泛型类型。

究其原因,在于Java中的泛型这一概念提出的目的,导致其只是作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦出,也就是说,成功编译过后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。

对此总结成一句话:泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。

四.类型通配符

接着上面的结论,我们知道,Box和Box实际上都是Box类型,现在需要继续探讨一个问题,那么在逻辑上,类似于Box和Box是否可以看成具有父子关系的泛型类型呢?

为了弄清这个问题,我们继续看下下面这个例子:

public class GenericTest {
	public static void main(String[] args) {
		Box<Number> name = new Box<Number>(99);
		Box<Integer> age = new Box<Integer>(712);
		getData(name);
		//The method getData(Box<Number>) in the type GenericTest is 
		//not applicable for the arguments (Box<Integer>)
		getData(age);
		// 1
	}
	public static void getData(Box<Number> data){
		System.out.println("data :" + data.getData());
	}
}

我们发现,在代码//1处出现了错误提示信息:The method getData(Box) in the t ype GenericTest is not applicable for the arguments (Box)。显然,通过提示信息,我们知道Box在逻辑上不能视为Box的父类。那么,原因何在呢?

public class GenericTest {
	public static void main(String[] args) {
		Box<Integer> a = new Box<Integer>(712);
		Box<Number> b = a;
		// 1
		Box<float> f = new Box<float>(3.14f);
		b.setData(f);
		// 2
	}
	public static void getData(Box<Number> data) {
		System.out.println("data :" + data.getData());
	}
}
class Box<T> {
	private T data;
	public Box() {
	}
	public Box(T data) {
		setData(data);
	}
	public T getData() {
		return data;
	}
	public void setData(T data) {
		this.data = data;
	}
}

这个例子中,显然//1和//2处肯定会出现错误提示的。在此我们可以使用反证法来进行说明。

假设Box在逻辑上可以视为Box的父类,那么//1和//2处将不会有错误提示了,那么问题就出来了,通过getData()方法取出数据时到底是什么类型呢?Integer? Float? 还是Number?且由于在编程过程中的顺序不可控性,导致在必要的时候必须要进行类型判断,且进行强制类型转换。显然,这与泛型的理念矛盾,因此,在逻辑上Box不能视为Box的父类。

好,那我们回过头来继续看“类型通配符”中的第一个例子,我们知道其具体的错误提示的深层次原因了。那么如何解决呢?总部能再定义一个新的函数吧。这和Java中的多态理念显然是违背的,因此,我们需要一个在逻辑上可以用来表示同时是Box和Box的父类的一个引用类型,由此,类型通配符应运而生。

类型通配符一般是使用 ? 代替具体的类型实参。注意了,此处是类型实参,而不是类型形参!且Box<?>在逻辑上是Box、Box…等所有Box<具体类型实参>的父类。由此,我们依然可以定义泛型方法,来完成此类需求。

public class GenericTest {
	public static void main(String[] args) {
		Box<String> name = new Box<String>("corn");
		Box<Integer> age = new Box<Integer>(712);
		Box<Number> number = new Box<Number>(314);
		getData(name);
		getData(age);
		getData(number);
	}
	public static void getData(Box<?> data) {
		System.out.println("data :" + data.getData());
	}
}

有时候,我们还可能听到类型通配符上限和类型通配符下限。具体有是怎么样的呢?

在上面的例子中,如果需要定义一个功能类似于getData()的方法,但对类型实参又有进一步的限制:只能是Number类及其子类。此时,需要用到类型通配符上限。

public class GenericTest {
	public static void main(String[] args) {
		Box<String> name = new Box<String>("corn");
		Box<Integer> age = new Box<Integer>(712);
		Box<Number> number = new Box<Number>(314);
		getData(name);
		getData(age);
		getData(number);
		//getUpperNumberData(name); // 1
		getUpperNumberData(age);
		// 2
		getUpperNumberData(number);
		// 3
	}
	public static void getData(Box<?> data) {
		System.out.println("data :" + data.getData());
	}
	public static void getUpperNumberData(Box<? extends Number> data){
		System.out.println("data :" + data.getData());
	}
}

此时,显然,在代码//1处调用将出现错误提示,而//2 //3处调用正常。

类型通配符上限通过形如Box<? extends Number>形式定义,相对应的,类型通配符下限为Box<? super Number>形式,其含义与类型通配符上限正好相反,在此不作过多阐述了。

五.话外篇

本文中的例子主要是为了阐述泛型中的一些思想而简单举出的,并不一定有着实际的可用性。另外,一提到泛型,相信大家用到最多的就是在集合中,其实,在实际的编程过程中,自己可以使用泛型去简化开发,且能很好的保证代码质量。并且还要注意的一点是,Java中没有所谓的泛型数组一说。

对于泛型,最主要的还是需要理解其背后的思想和目的。

Java_supermanNO1:专注于Java开发技术的研究与知识分享!

————END————

  • 点赞(编辑不易,感谢您的支持)
  • …
  • 转发(分享知识,传播快乐)
  • …
  • 关注(每天更新Java开发技术)
  • …
【Java架构师入门到精通】架构师图谱 1、架构师图谱 1.2 Java架构师图谱.jpg 一致性图谱.jpg 1.5 互联网大流量的方法.jpg 阿里巴巴常用小框架.jpg 1.8 架构方法论图谱.jpg 1.9 设计模式秘籍图谱.jpg 2.1 JVM垃圾回图谱.png 2.2 Java并发图谱.jpg 2.3 Java集合图谱.jpg 2.4 Java集合类图.jpg 2.5 Java List类图.jpg 2.6 Java Map类图.jpg 2.7 Java Set类图.jpg 一般Java架构设计师主要完成 阅读详情

相关推荐

TOD和PPS精确时间同步技术

授时

u010783226的专栏 1万+

Java数据结构基础——泛型、通配符

6000字速学泛型及通配符

chenchenchencl的博客 4757

自适应滤波算法综述

自适应滤波算法综述

xdzhujy的博客 5万+

Java泛型(通配符)

Java泛型通配符 在了解通配符之前,如下知识点的理解对于为何设置通配符有着很好的解释作用。 协变: 不变: 逆变: 更加详细的解释可参考文章:《几个搞不太懂的术语:逆变、协变、不变》 ...

weixin_44298385的博客 4373

IDEA系列(四):IDEA导入Maven工程项目并配置Tomcat启动

本片文章主要介绍如何导入一个存在的maven项目并配置Tomcat启动项目,方便自己使用,也分享出来,希望可以帮助到其他人。

低调D树苗的博客 1244

Python小白避坑指南:用Ursina做3D图形,Entity的scale和color参数到底怎么调才不出错?

本文详细解析了Python Ursina引擎中Entity对象的scale和color参数调优技巧,帮助3D图形编程初学者避开常见陷阱。通过对比实验和典型场景分析,深入讲解三种缩放方式的区别、颜色定义的四种方法,以及参数组合的协同效应,助力开发者精准控制3D图形表现。

weixin_26782929的博客 413

Java学习笔记(十二):泛型的使用

来源:http://www.cnblogs.com/lwbqqyumidi/p/3837629.htmlJava总结篇系列:Java泛型 一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码:public class GenericTest { public static void main(String[] args) { List list = ne

汤圆学Java 982

UG NX二次开发(C#)-外部模式-批量删除某些图层中的体对象和曲线对象

在 UG NX中,有时需要批量删除某文件夹下多个.prt文件中固定一些图层中的体对象和曲线对象,这时如果采用手动逐个打开模型,并选择针对的图层删除,即耗时也容易遗漏,因此采用外部模式来处理比较方便。本文介绍批量删除某些图层中的体对象和曲线对象。

GimiGimmy 3035

Java数据结构基础——泛型、通配符_java通配符和泛型

一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。只接受 Number 的子类型作为 E 的类型,实参没有指定类型边界 E,可以视为 E extends Object。实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值。使用Object数组的缺点有二,存放元素时可以存放任何类型的元素,再者,取出元素的时候需要手动强转。因此,Java的泛型机制是在编译级别实现的。注意:泛型时在编译的时候的一种机制,在运行时是没有泛型的概念的。

2401_89734329的博客 1405

ESD防护设计宝典(十):RE(辐射发射)超标问题排查与解决

RE测试是EMC认证的“头号杀手”。当屏幕上出现一根根超标频谱线时,如何快速定位元凶并有效整改?本讲将带你化身电磁侦探,完成一次完美的RE问题“缉凶”。

m0_56451176的博客 396

交通规划仿真软件:TransCAD_(7).公交系统规划与分析

通过TransCAD进行公交系统规划与分析,可以有效地评估公交网络的性能,优化线路设计,提高服务质量。数据准备、模型建立、仿真运行和结果分析是公交系统规划与分析的关键步骤。在实际应用中,规划者和分析师可以根据仿真结果提出具体的优化建议,不断完善公交系统的运行效率和乘客体验。

kkchenjj的博客 957

面试官:什么是泛型擦除、泛型上界、泛型下界、PECS原则?

泛型的本质是 类型参数化,解决类型爆炸的问题。所谓泛型是指将类型参数化,以达到代码复用提高软件开发工作效率的一种数据类型。比如: 如果我们的代码中存在很多的 食物类型, 继承关系如下然后我们要定义一个盘子 plate,注意这个盘子除了 装入食物food之外,还可以装其他的比如 小玩具。(1) 装水果的盘子 FruitPlate(2) 装肉的盘子 MeatPlate(3) 装苹果的盘子 ApplePlate(4) 装香蕉的盘子 BananaPlate.....

架构师尼恩 1285

【电机应用控制】——直流有刷电机&驱动板/编码器介绍&PID算法&实操代码思路

声明:学习笔记来自正点原子B站教程,仅供学习交流!!玩具车、平衡车、无人机、印刷机、打印机、手机振动马达等电机即电动机(motor),也叫作马达,电能转化为机械能。按电源:直流、交流按用途:驱动用、控制用按运转速度:高速、低速、恒速、调速直流电机(有刷、无刷)、舵机、步进电机、伺服电机1、直流有刷电机(Brushed DC Motor,简称BDC)是内含电刷装置的将直流电能转化为机械能的电动机。例如四驱赛车四个马达操控方便、成本低、维护时换电刷即可;

weixin_51658186的博客 2万+

再见,Java泛型 T、E、K、V、?。通用泛型要来了,非常劲爆!

因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享点击关注#互联网架构师公众号,领取架构师全套资料 都在这里0、2T架构师学习资料干货分上一篇:深入浅出监控神器Prometheus大家好,我是互联网架构师!Infoworld 消息指出,根据 OpenJDK 提案,Java 将获得通用泛型(universal generics),此举旨在使该语言更易于使...

emprere的博客 213

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

JAVA从菜鸟到架构师系列课程

JAVA从菜鸟到架构师系列课程 【入门篇】 J2SE的Socket网络编程应用 J2SE的反射机制高级应用 J2SE高深讲解 JAVA编程思想 中级教程 JAVA编程思想 初级教程 JAVA编程思想 高级教程 基于J2SE的QQ聊天工具开发 我来说说面向对象 【进阶篇】 CRM项目 Eclipse Hibernate JAVA WEB开发视频 JAVAWEB开发实战经典-高级案例篇 JAV...

lyb9292的博客 1476

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

阿里Java P系列技术要求(P5-P7)

阿里p系列薪资(最新数据比这个高1倍左右) 阿里P5(高级研发工程师) 工作要求: 能独立完成日常工作,并能够对一些方案提出自己的建议。基本考核就是能上手独立完成工作,熟练掌握。 技能要求(熟练): 1、程序设计和开发。 2、工作中需用到的Java开发的技术点以及相关的其他技术点。 3、工作中需用到的Web开发的技术点以及相关的其他技术点。 4、工作中需要用到的数据库技术点以...

一个有情怀的程序猿博客 6699

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

9大架构师联合首发Android架构师学习大纲,对标阿里P7,年薪60W+不再是梦

前言: 现如今21世纪已成为互联网时代,越来越多的毕业生选择了互联网工作,从事移动开发的更是不在少数,而如何成为一名优秀的Android架构师却成为了大数程序员苦恼的问题,尽管在学校学了不少专业知识技术,可缺少实战经验,虽说网上有太多的学习资料,可又太过于零散,不够体系。作为一位曾经的面试官也是深知这一点的。 但有问题就会有解决的办法,针对这一系列的问题,阿里9位架构师联合打造了一份架构师学习大纲,不仅将Android各个知识点详细列举出来了,更是将学习方法,学习思路和学习路线通通概括在其中,让你对从基础的

Android 开发架构 719

Android使用ViewPager实现图片轮播系列之一:简单实现,2024最新阿里Android高级面试题及答案

]

533

9大架构师联合首发Android架构师学习大纲,对标阿里P7,年薪60W

现如今21世纪已成为互联网时代,越来越多的毕业生选择了互联网工作,从事移动开发的更是不在少数,而如何成为一名优秀的Android架构师却成为了大数程序员苦恼的问题,尽管在学校学了不少专业知识技术,可缺少实战经验,虽说网上有太多的学习资料,可又太过于零散,不够体系。作为一位曾经的面试官也是深知这一点的。 但有问题就会有解决的办法,针对这一系列的问题,阿里9位架构师联合打造了一份架构师学习大纲,不仅将Android各个知识点详细列举出来了,更是将学习方法,学习思路和学习路线通通概括在其中,让你对从基础的入门到资

m0_66144910的博客 390

安卓资深架构师分享学习经验及总结,吊打面试官系列!_资深安卓系统架构师面试

给大家送上我成功跳槽复习中所整理的资料,由于文章篇幅有限,所以只是把题目列出来了网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。需要这份系统化学习资料的朋友,可以戳这里获取一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

2401_84520377的博客 692

java开发三年想去阿里?阿里架构师给你的规划建议请查收

java开发三年想去阿里?阿里架构师给你的规划建议请查收! 阿里内部的常见级别和定义 P序列=技术岗 M序列=管理岗 阿里的非管理岗分为10级,其中P6、P7、P8需求量最大,也是阿里占比最大的级别。 备注:现在的阿里P系列,水分较大,与我印象中09年那会我们在淘宝那会了不可同日而语。主要还是阿里现在业务太广,对技术的需求缺口太大了有关,现在已经明显放低P系列的标准了。为啥?需求太旺盛啊,这么多业务板块。 阿里的级别对应薪资 阿里薪资结构:一般是12+1+3=16薪,年底的奖金为0-6.

javassb的博客 201

java架构师进阶之路

包含了计算机基础、算法和数据结构、常用工具、java核心知识、性能优化、基础框架、数据库、消息队列、缓存中间件、搜索引擎、大数据、RPC、网关、容器、面试等知识

henhenha的博客 5843

完整详解阿里Java P5-P8百万年薪架构师的技能要求!

疫情高峰期过去了,金三银四也来临了,最近很多同学给我留言:关于阿里的Java P系列薪资与技能的问题,本篇统一解答大家的疑惑。先晒一个大家最关心的薪资结构,最新的薪资结构,个人建议参考。好吧,下面我就逐一解读阿里Java 从P5到P8架构师的岗位与技能要求。

stone_tmp的博客 1636

五年Java开发工作经验,学完阿里P8级架构师的6+2落地项目,跳槽阿里涨薪到50W+,漂亮!

前言 统一说明一下,楼主是研究生,一般的985毕业,之前在工作了5年,做过的大项目数不胜数,比如再造淘宝项目落地实战,某滴网约车项目,多人在线即时对战网游服务器,和家云服务平台,前后端分离某喵微信商城,亿级流量多级缓存平台,亚马逊电商个性化推荐系统,IOT流云式平台,阿里巴巴中台实战,年初跳槽后去阿里面试6轮之后定级是P6。 做过的项目大纲 目前在阿里,给我的薪资已经是P6的最高水平了。为什么定位还是P6,我也很绝望呀! 也有人觉得阿里现在觉得所有其他公司想跳槽...

+W❤:bjmsb2019 451

最全阿里架构师P系列解读:P5-P8的技能要求和薪资结构

2018年持续一整年的架构设计分享,2019年我希望持续分享的同时,能真正意义上帮助到部分读者成为一名架构师。 学习的同时请千万别:只见树木,不见森林。 所以我会让大家先俯瞰完整的森林,我们再从树木开始,一起去穿越整个森林。 最新阿里技术P系列薪资:上图薪资结构*2 阿里P5(高级研发工程师) 1.工作要求: 能独立完成日常工作,并能够对一些方案提出自己的建议。 基本考核就是能上手独立完成工作,...

一个有情怀的程序猿博客 9964

Java架构师面试专题系列(含答案)

Java架构师面试专题系列(含答案),年底福利限时领取! java架构交流 2018-12-31 16:51:08 学习是一份苦差事,这句话真的不是说说而已,真的是你认真学习过,才会懂得,学习是多么的辛苦,这点我深有体会,但是我还是想说,没办法,想要更好的生活,你就要不断地努力学习。 所幸的是,程序员这个行业,学习和回报率是要高于其他行业的,不断提升自己的技术水平和认知,是绝对没有坏处的。 ...

u013322876的博客 1万+
上一篇: 阿里架构师的Java总结篇系列——Java多线程(三)
下一篇: Java的常用开发工具总汇
Java_supermanNO1
博客等级 码龄7年 1170粉丝 329原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值