当前位置: 首页 > 编程日记 > 正文

泛型java 代码讲解_Java泛型详解

986f732ed2f1

2516326-5475e88a458a09e4.png

一,打破砂锅问到底

泛型存在的意义?

泛型类,泛型接口,泛型方法如何定义?

如何限定类型变量?

泛型中使用的约束和局限性有哪些?

泛型类型的继承规则是什么?

泛型中的通配符类型是什么?

如何获取泛型的参数类型?

虚拟机是如何实现泛型的?

在日常开发中是如何运用泛型的?

986f732ed2f1

Java泛型详解.png

二,晓之以理动之以码

1,泛型的定义以及存在意义

泛型,即“参数化类型”。就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

例如:GenericClass{}

一些常用的泛型类型变量:

E:元素(Element),多用于java集合框架

K:关键字(Key)

N:数字(Number)

T:类型(Type)

V:值(Value)

如果要实现不同类型的加法,每种类型都需要重载一个add方法

package com.jay.java.泛型.needGeneric;

/**

* Author:Jay On 2019/5/9 16:06

*

* Description: 为什么使用泛型

*/

public class NeedGeneric1 {

private static int add(int a, int b) {

System.out.println(a + "+" + b + "=" + (a + b));

return a + b;

}

private static float add(float a, float b) {

System.out.println(a + "+" + b + "=" + (a + b));

return a + b;

}

private static double add(double a, double b) {

System.out.println(a + "+" + b + "=" + (a + b));

return a + b;

}

private static double add(T a, T b) {

System.out.println(a + "+" + b + "=" + (a.doubleValue() + b.doubleValue()));

return a.doubleValue() + b.doubleValue();

}

public static void main(String[] args) {

NeedGeneric1.add(1, 2);

NeedGeneric1.add(1f, 2f);

NeedGeneric1.add(1d, 2d);

NeedGeneric1.add(Integer.valueOf(1), Integer.valueOf(2));

NeedGeneric1.add(Float.valueOf(1), Float.valueOf(2));

NeedGeneric1.add(Double.valueOf(1), Double.valueOf(2));

}

}

取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易现“java.lang. ClassCast Exception”异常。

package com.jay.java.泛型.needGeneric;

import java.util.ArrayList;

import java.util.List;

/**

* Author:Jay On 2019/5/9 16:23

*

* Description: 为什么要使用泛型

*/

public class NeedGeneric2 {

static class C{

}

public static void main(String[] args) {

List list=new ArrayList();

list.add("A");

list.add("B");

list.add(new C());

list.add(100);

//1.当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。

//2.因此,//1处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现“java.lang.ClassCastException”异常。

for (int i = 0; i < list.size(); i++) {

// System.out.println(list.get(i));

String value= (String) list.get(i);

System.out.println(value);

}

}

}

所以使用泛型的意义在于

1,适用于多种数据类型执行相同的代码(代码复用)

2, 泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)

2,泛型类的使用

定义一个泛型类:public class GenericClass{}

package com.jay.java.泛型.DefineGeneric;

/**

* Author:Jay On 2019/5/9 16:49

*

* Description: 泛型类

*/

public class GenericClass {

private T data;

public T getData() {

return data;

}

public void setData(T data) {

this.data = data;

}

public static void main(String[] args) {

GenericClass genericClass=new GenericClass<>();

genericClass.setData("Generic Class");

System.out.println(genericClass.getData());

}

}

3,泛型接口的使用

定义一个泛型接口:public interface GenericIntercace{}

/**

* Author:Jay On 2019/5/9 16:57

*

* Description: 泛型接口

*/

public interface GenericIntercace {

T getData();

}

实现泛型接口方式一:public class ImplGenericInterface1 implements GenericIntercace

/**

* Author:Jay On 2019/5/9 16:59

*

* Description: 泛型接口实现类-泛型类实现方式

*/

public class ImplGenericInterface1 implements GenericIntercace {

private T data;

private void setData(T data) {

this.data = data;

}

@Override

public T getData() {

return data;

}

public static void main(String[] args) {

ImplGenericInterface1 implGenericInterface1 = new ImplGenericInterface1<>();

implGenericInterface1.setData("Generic Interface1");

System.out.println(implGenericInterface1.getData());

}

}

实现泛型接口方式二:public class ImplGenericInterface2 implements GenericIntercace {}

/**

* Author:Jay On 2019/5/9 17:01

*

* Description: 泛型接口实现类-指定具体类型实现方式

*/

public class ImplGenericInterface2 implements GenericIntercace {

@Override

public String getData() {

return "Generic Interface2";

}

public static void main(String[] args) {

ImplGenericInterface2 implGenericInterface2 = new ImplGenericInterface2();

System.out.println(implGenericInterface2.getData());

}

}

4,泛型方法的使用

定义一个泛型方法: private static TgenericAdd(T a, T b) {}

/**

* Author:Jay On 2019/5/10 10:46

*

* Description: 泛型方法

*/

public class GenericMethod1 {

private static int add(int a, int b) {

System.out.println(a + "+" + b + "=" + (a + b));

return a + b;

}

private static T genericAdd(T a, T b) {

System.out.println(a + "+" + b + "="+a+b);

return a;

}

public static void main(String[] args) {

GenericMethod1.add(1, 2);

GenericMethod1.genericAdd("a", "b");

}

}

/**

* Author:Jay On 2019/5/10 16:22

*

* Description: 泛型方法

*/

public class GenericMethod3 {

static class Animal {

@Override

public String toString() {

return "Animal";

}

}

static class Dog extends Animal {

@Override

public String toString() {

return "Dog";

}

}

static class Fruit {

@Override

public String toString() {

return "Fruit";

}

}

static class GenericClass {

public void show01(T t) {

System.out.println(t.toString());

}

public void show02(T t) {

System.out.println(t.toString());

}

public void show03(K k) {

System.out.println(k.toString());

}

}

public static void main(String[] args) {

Animal animal = new Animal();

Dog dog = new Dog();

Fruit fruit = new Fruit();

GenericClass genericClass = new GenericClass<>();

//泛型类在初始化时限制了参数类型

genericClass.show01(dog);

// genericClass.show01(fruit);

//泛型方法的参数类型在使用时指定

genericClass.show02(dog);

genericClass.show02(fruit);

genericClass.show03(animal);

genericClass.show03(dog);

genericClass.show03(fruit);

// genericClass.show03(animal);

}

}

5,限定泛型类型变量

1,对类的限定:public class TypeLimitForClass{}

2,对方法的限定:public static>T getMin(T a, T b) {}

/**

* Author:Jay On 2019/5/10 16:38

*

* Description: 类型变量的限定-方法

*/

public class TypeLimitForMethod {

/**

* 计算最小值

* 如果要实现这样的功能就需要对泛型方法的类型做出限定

*/

// private static T getMin(T a, T b) {

// return (a.compareTo(b) > 0) ? a : b;

// }

/**

* 限定类型使用extends关键字指定

* 可以使类,接口,类放在前面接口放在后面用&符号分割

* 例如: & Serializable>

*/

public static > T getMin(T a, T b) {

return (a.compareTo(b) < 0) ? a : b;

}

public static void main(String[] args) {

System.out.println(TypeLimitForMethod.getMin(2, 4));

System.out.println(TypeLimitForMethod.getMin("a", "r"));

}

}

/**

* Author:Jay On 2019/5/10 17:02

*

* Description: 类型变量的限定-类

*/

public class TypeLimitForClass {

private T data;

public T getData() {

return data;

}

public void setData(T data) {

this.data = data;

}

public static void main(String[] args) {

ArrayList stringArrayList = new ArrayList<>();

stringArrayList.add("A");

stringArrayList.add("B");

ArrayList integerArrayList = new ArrayList<>();

integerArrayList.add(1);

integerArrayList.add(2);

integerArrayList.add(3);

TypeLimitForClass typeLimitForClass01 = new TypeLimitForClass<>();

typeLimitForClass01.setData(stringArrayList);

TypeLimitForClass typeLimitForClass02 = new TypeLimitForClass<>();

typeLimitForClass02.setData(integerArrayList);

System.out.println(getMinListSize(typeLimitForClass01.getData().size(), typeLimitForClass02.getData().size()));

}

public static > T getMinListSize(T a, T b) {

return (a.compareTo(b) < 0) ? a : b;

}

6,泛型中的约束和局限性

1,不能实例化泛型类

2,静态变量或方法不能引用泛型类型变量,但是静态泛型方法是可以的

3,基本类型无法作为泛型类型

4,无法使用instanceof关键字或==判断泛型类的类型

5,泛型类的原生类型与所传递的泛型无关,无论传递什么类型,原生类是一样的

6,泛型数组可以声明但无法实例化

7,泛型类不能继承Exception或者Throwable

8,不能捕获泛型类型限定的异常但可以将泛型限定的异常抛出

/**

* Author:Jay On 2019/5/10 17:41

*

* Description: 泛型的约束和局限性

*/

public class GenericRestrict1 {

static class NormalClass {

}

private T data;

/**

* 不能实例化泛型类

* Type parameter 'T' cannot be instantiated directly

*/

public void setData() {

//this.data = new T();

}

/**

* 静态变量或方法不能引用泛型类型变量

* 'com.jay.java.泛型.restrict.GenericRestrict1.this' cannot be referenced from a static context

*/

// private static T result;

// private static T getResult() {

// return result;

// }

/**

* 静态泛型方法是可以的

*/

private static K getKey(K k) {

return k;

}

public static void main(String[] args) {

NormalClass normalClassA = new NormalClass();

NormalClass normalClassB = new NormalClass();

/**

* 基本类型无法作为泛型类型

*/

// GenericRestrict1 genericRestrictInt = new GenericRestrict1<>();

GenericRestrict1 genericRestrictInteger = new GenericRestrict1<>();

GenericRestrict1 genericRestrictString = new GenericRestrict1<>();

/**

* 无法使用instanceof关键字判断泛型类的类型

* Illegal generic type for instanceof

*/

// if(genericRestrictInteger instanceof GenericRestrict1){

// return;

// }

/**

* 无法使用“==”判断两个泛型类的实例

* Operator '==' cannot be applied to this two instance

*/

// if (genericRestrictInteger == genericRestrictString) {

// return;

// }

/**

* 泛型类的原生类型与所传递的泛型无关,无论传递什么类型,原生类是一样的

*/

System.out.println(normalClassA == normalClassB);//false

System.out.println(genericRestrictInteger == genericRestrictInteger);//

System.out.println(genericRestrictInteger.getClass() == genericRestrictString.getClass()); //true

System.out.println(genericRestrictInteger.getClass());//com.jay.java.泛型.restrict.GenericRestrict1

System.out.println(genericRestrictString.getClass());//com.jay.java.泛型.restrict.GenericRestrict1

/**

* 泛型数组可以声明但无法实例化

* Generic array creation

*/

GenericRestrict1[] genericRestrict1s;

// genericRestrict1s = new GenericRestrict1[10];

genericRestrict1s = new GenericRestrict1[10];

genericRestrict1s[0]=genericRestrictString;

}

}

/**

* Author:Jay On 2019/5/10 18:45

*

* Description: 泛型和异常

*/

public class GenericRestrict2 {

private class MyException extends Exception {

}

/**

* 泛型类不能继承Exception或者Throwable

* Generic class may not extend 'java.lang.Throwable'

*/

// private class MyGenericException extends Exception {

// }

//

// private class MyGenericThrowable extends Throwable {

// }

/**

* 不能捕获泛型类型限定的异常

* Cannot catch type parameters

*/

public void getException(T t) {

// try {

//

// } catch (T e) {

//

// }

}

/**

*可以将泛型限定的异常抛出

*/

public void getException(T t) throws T {

try {

} catch (Exception e) {

throw t;

}

}

}

7,泛型类型继承规则

1,对于泛型参数是继承关系的泛型类之间是没有继承关系的

2,泛型类可以继承其它泛型类,例如: public class ArrayList extends AbstractList

3,泛型类的继承关系在使用中同样会受到泛型类型的影响

/**

* Author:Jay On 2019/5/10 19:13

*

* Description: 泛型继承规则测试类

*/

public class GenericInherit {

private T data1;

private T data2;

public T getData1() {

return data1;

}

public void setData1(T data1) {

this.data1 = data1;

}

public T getData2() {

return data2;

}

public void setData2(T data2) {

this.data2 = data2;

}

public static void setData2(GenericInherit data2) {

}

public static void main(String[] args) {

// Son 继承自 Father

Father father = new Father();

Son son = new Son();

GenericInherit fatherGenericInherit = new GenericInherit<>();

GenericInherit sonGenericInherit = new GenericInherit<>();

SubGenericInherit fatherSubGenericInherit = new SubGenericInherit<>();

SubGenericInherit sonSubGenericInherit = new SubGenericInherit<>();

/**

* 对于传递的泛型类型是继承关系的泛型类之间是没有继承关系的

* GenericInherit 与GenericInherit 没有继承关系

* Incompatible types.

*/

father = new Son();

// fatherGenericInherit=new GenericInherit();

/**

* 泛型类可以继承其它泛型类,例如: public class ArrayList extends AbstractList

*/

fatherGenericInherit=new SubGenericInherit();

/**

*泛型类的继承关系在使用中同样会受到泛型类型的影响

*/

setData2(fatherGenericInherit);

// setData2(sonGenericInherit);

setData2(fatherSubGenericInherit);

// setData2(sonSubGenericInherit);

}

private static class SubGenericInherit extends GenericInherit {

}

8,通配符类型

1, extends Parent> 指定了泛型类型的上届

2, super Child> 指定了泛型类型的下届

3, > 指定了没有限制的泛型类型

986f732ed2f1

通配符测试类结构.png

/**

* Author:Jay On 2019/5/10 19:51

*

* Description: 泛型通配符测试类

*/

public class GenericByWildcard {

private static void print(GenericClass fruitGenericClass) {

System.out.println(fruitGenericClass.getData().getColor());

}

private static void use() {

GenericClass fruitGenericClass = new GenericClass<>();

print(fruitGenericClass);

GenericClass orangeGenericClass = new GenericClass<>();

//类型不匹配,可以使用 extends Parent> 来解决

// print(orangeGenericClass);

}

/**

* extends Parent> 指定了泛型类型的上届

*/

private static void printExtends(GenericClass extends Fruit> genericClass) {

System.out.println(genericClass.getData().getColor());

}

public static void useExtend() {

GenericClass fruitGenericClass = new GenericClass<>();

printExtends(fruitGenericClass);

GenericClass orangeGenericClass = new GenericClass<>();

printExtends(orangeGenericClass);

GenericClass foodGenericClass = new GenericClass<>();

//Food是Fruit的父类,超过了泛型上届范围,类型不匹配

// printExtends(foodGenericClass);

//表示GenericClass的类型参数的上届是Fruit

GenericClass extends Fruit> extendFruitGenericClass = new GenericClass<>();

Apple apple = new Apple();

Fruit fruit = new Fruit();

/*

* 道理很简单,? extends X 表示类型的上界,类型参数是X的子类,那么可以肯定的说,

* get方法返回的一定是个X(不管是X或者X的子类)编译器是可以确定知道的。

* 但是set方法只知道传入的是个X,至于具体是X的那个子类,不知道。

* 总结:主要用于安全地访问数据,可以访问X及其子类型,并且不能写入非null的数据。

*/

// extendFruitGenericClass.setData(apple);

// extendFruitGenericClass.setData(fruit);

fruit = extendFruitGenericClass.getData();

}

/**

* super Child> 指定了泛型类型的下届

*/

public static void printSuper(GenericClass super Apple> genericClass) {

System.out.println(genericClass.getData());

}

public static void useSuper() {

GenericClass foodGenericClass = new GenericClass<>();

printSuper(foodGenericClass);

GenericClass fruitGenericClass = new GenericClass<>();

printSuper(fruitGenericClass);

GenericClass appleGenericClass = new GenericClass<>();

printSuper(appleGenericClass);

GenericClass hongFuShiAppleGenericClass = new GenericClass<>();

// HongFuShiApple 是Apple的子类,达不到泛型下届,类型不匹配

// printSuper(hongFuShiAppleGenericClass);

GenericClass orangeGenericClass = new GenericClass<>();

// Orange和Apple是兄弟关系,没有继承关系,类型不匹配

// printSuper(orangeGenericClass);

//表示GenericClass的类型参数的下界是Apple

GenericClass super Apple> supperAppleGenericClass = new GenericClass<>();

supperAppleGenericClass.setData(new Apple());

supperAppleGenericClass.setData(new HongFuShiApple());

/*

* ? super X 表示类型的下界,类型参数是X的超类(包括X本身),

* 那么可以肯定的说,get方法返回的一定是个X的超类,那么到底是哪个超类?不知道,

* 但是可以肯定的说,Object一定是它的超类,所以get方法返回Object。

* 编译器是可以确定知道的。对于set方法来说,编译器不知道它需要的确切类型,但是X和X的子类可以安全的转型为X。

* 总结:主要用于安全地写入数据,可以写入X及其子类型。

*/

// supperAppleGenericClass.setData(new Fruit());

//get方法只会返回一个Object类型的值。

Object data = supperAppleGenericClass.getData();

}

/**

* > 指定了没有限定的通配符

*/

public static void printNonLimit(GenericClass> genericClass) {

System.out.println(genericClass.getData());

}

public static void useNonLimit() {

GenericClass foodGenericClass = new GenericClass<>();

printNonLimit(foodGenericClass);

GenericClass fruitGenericClass = new GenericClass<>();

printNonLimit(fruitGenericClass);

GenericClass appleGenericClass = new GenericClass<>();

printNonLimit(appleGenericClass);

GenericClass> genericClass = new GenericClass<>();

//setData 方法不能被调用, 甚至不能用 Object 调用;

// genericClass.setData(foodGenericClass);

// genericClass.setData(new Object());

//返回值只能赋给 Object

Object object = genericClass.getData();

}

}

9,获取泛型的参数类型

Type是什么

这里的Type指java.lang.reflect.Type, 是Java中所有类型的公共高级接口, 代表了Java中的所有类型. Type体系中类型的包括:数组类型(GenericArrayType)、参数化类型(ParameterizedType)、类型变量(TypeVariable)、通配符类型(WildcardType)、原始类型(Class)、基本类型(Class), 以上这些类型都实现Type接口.

参数化类型,就是我们平常所用到的泛型List、Map;

数组类型,并不是我们工作中所使用的数组String[] 、byte[],而是带有泛型的数组,即T[] ;

通配符类型, 指的是>, extends T>等等

原始类型, 不仅仅包含我们平常所指的类,还包括枚举、数组、注解等;

基本类型, 也就是我们所说的java的基本类型,即int,float,double等

public interface ParameterizedType extends Type {

// 返回确切的泛型参数, 如Map返回[String, Integer]

Type[] getActualTypeArguments();

//返回当前class或interface声明的类型, 如List>返回List

Type getRawType();

//返回所属类型. 如,当前类型为O.I, 则返回O. 顶级类型将返回null

Type getOwnerType();

}

/**

* Author:Jay On 2019/5/11 22:41

*

* Description: 获取泛型类型测试类

*/

public class GenericType {

private T data;

public T getData() {

return data;

}

public void setData(T data) {

this.data = data;

}

public static void main(String[] args) {

GenericType genericType = new GenericType() {};

Type superclass = genericType.getClass().getGenericSuperclass();

//getActualTypeArguments 返回确切的泛型参数, 如Map返回[String, Integer]

Type type = ((ParameterizedType) superclass).getActualTypeArguments()[0];

System.out.println(type);//class java.lang.String

}

}

10,虚拟机是如何实现泛型的

Java泛型是Java1.5之后才引入的,为了向下兼容。Java采用了C++完全不同的实现思想。Java中的泛型更多的看起来像是编译期用的

Java中泛型在运行期是不可见的,会被擦除为它的上级类型。如果是没有限定的泛型参数类型,就会被替换为Object.

GenericClass stringGenericClass=new GenericClass<>();

GenericClass integerGenericClass=new GenericClass<>();

C++中GenericClass和GenericClass是两个不同的类型

Java进行了类型擦除之后统一改为GenericClass

/**

* Author:Jay On 2019/5/11 16:11

*

* Description:泛型原理测试类

*/

public class GenericTheory {

public static void main(String[] args) {

Map map = new HashMap<>();

map.put("Key", "Value");

System.out.println(map.get("Key"));

GenericClass genericClass = new GenericClass<>();

genericClass.put("Key", "Value");

System.out.println(genericClass.get("Key"));

}

public static class GenericClass {

private K key;

private V value;

public void put(K key, V value) {

this.key = key;

this.value = value;

}

public V get(V key) {

return value;

}

}

/**

* 类型擦除后GenericClass2

* @param

*/

private class GenericClass2 {

}

/**

* 类型擦除后GenericClass3

* 当使用到Serializable时会将相应代码强制转换为Serializable

* @param

*/

private class GenericClass3 {

}

}

对应的字节码文件

public static void main(String[] args) {

Map map = new HashMap();

map.put("Key", "Value");

System.out.println((String)map.get("Key"));

GenericTheory.GenericClass genericClass = new GenericTheory.GenericClass();

genericClass.put("Key", "Value");

System.out.println((String)genericClass.get("Key"));

}

三,学以致用

1,泛型解析JSON数据封装

api返回的json数据

{

"code":200,

"msg":"成功",

"data":{

"name":"Jay",

"email":"10086"

}

}

BaseResponse .java

/**

* Author:Jay On 2019/5/11 20:48

*

* Description: 接口数据接收基类

*/

public class BaseResponse {

private int code;

private String msg;

public int getCode() {

return code;

}

public void setCode(int code) {

this.code = code;

}

public String getMsg() {

return msg;

}

public void setMsg(String msg) {

this.msg = msg;

}

}

UserResponse.java

/**

* Author:Jay On 2019/5/11 20:49

*

* Description: 用户信息接口实体类

*/

public class UserResponse extends BaseResponse {

private T data;

public T getData() {

return data;

}

public void setData(T data) {

this.data = data;

}

}

2,泛型+反射实现巧复用工具类

/**

* Author:Jay On 2019/5/11 21:05

*

* Description: 泛型相关的工具类

*/

public class GenericUtils {

public static class Movie {

private String name;

private Date time;

public String getName() {

return name;

}

public Date getTime() {

return time;

}

public Movie(String name, Date time) {

this.name = name;

this.time = time;

}

@Override

public String toString() {

return "Movie{" + "name='" + name + '\'' + ", time=" + time + '}';

}

}

public static void main(String[] args) {

List movieList = new ArrayList<>();

for (int i = 0; i < 5; i++) {

movieList.add(new Movie("movie" + i, new Date()));

}

System.out.println("排序前:" + movieList.toString());

GenericUtils.sortAnyList(movieList, "name", true);

System.out.println("按name正序排:" + movieList.toString());

GenericUtils.sortAnyList(movieList, "name", false);

System.out.println("按name逆序排:" + movieList.toString());

}

/**

* 对任意集合的排序方法

* @param targetList 要排序的实体类List集合

* @param sortField 排序字段

* @param sortMode true正序,false逆序

*/

public static void sortAnyList(List targetList, final String sortField, final boolean sortMode) {

if (targetList == null || targetList.size() < 2 || sortField == null || sortField.length() == 0) {

return;

}

Collections.sort(targetList, new Comparator() {

@Override

public int compare(Object obj1, Object obj2) {

int retVal = 0;

try {

// 获取getXxx()方法名称

String methodStr = "get" + sortField.substring(0, 1).toUpperCase() + sortField.substring(1);

Method method1 = ((T) obj1).getClass().getMethod(methodStr, null);

Method method2 = ((T) obj2).getClass().getMethod(methodStr, null);

if (sortMode) {

retVal = method1.invoke(((T) obj1), null).toString().compareTo(method2.invoke(((T) obj2), null).toString());

} else {

retVal = method2.invoke(((T) obj2), null).toString().compareTo(method1.invoke(((T) obj1), null).toString());

}

} catch (Exception e) {

System.out.println("List排序异常!");

e.printStackTrace();

}

return retVal;

}

});

}

}

3,Gson库中的泛型的使用-TypeToken

/**

* Author:Jay On 2019/5/11 22:11

*

* Description: Gson库中的泛型使用

*/

public class GsonGeneric {

public static class Person {

private String name;

private int age;

public Person(String name, int age) {

this.name = name;

this.age = age;

}

@Override

public String toString() {

return "Person{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

}

public static void main(String[] args) {

Gson gson = new Gson();

List personList = new ArrayList<>();

for (int i = 0; i < 5; i++) {

personList.add(new Person("name" + i, 18 + i));

}

// Serialization

String json = gson.toJson(personList);

System.out.println(json);

// Deserialization

Type personType = new TypeToken>() {}.getType();

List personList2 = gson.fromJson(json, personType);

System.out.println(personList2);

}

}

相关文章:

(转)金额转中文大写

public class RMB {//返回转换好的大写形式public static String numberToRMB(String money) {return cleanZero(splitNum(roundString(money)));}// 将小写金额转换成大写金额private static String splitNum(String s) {// 如果传入的是空串则继续返回空串if ("".e…

[IOS]UIWebView实现保存页面和读取服务器端json数据

如何通过viewView保存访问过的页面&#xff1f;和如何获取并解析服务器端发送过来的json数据&#xff1f;通过一个简单的Demo来学习一下吧&#xff01; 操作步骤&#xff1a; 1.创建SingleViewApplication应用&#xff0c;新建VIewController&#xff0c;并在xib试图中添加WebV…

struts2之配置文件struts.xml详解

struts配置文件 struts.xml配置参数详解 struts.xml中很大一部分配置默认配置就好了 但是有些还是需要做了解 以便于理解 和修改 <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Str…

ceph bluestore 源码分析:刷缓存(trim)逻辑

环境 ceph版本&#xff1a;12.2.1 部署模式&#xff1a;ec 21 osd&#xff1a; 3个 且资源池已经有数据 执行命令&#xff1a;ceph daemon osd.0 flush_store_cache 进行刷缓存。即将dump_mempools内存池管理的bluestore cache中的无用数据进行释放 主要参数: bluestore_cac…

php中怎么过滤器_PHP 过滤器(Filter)

过滤多个输入表单通常由多个输入字段组成。为了避免对 filter_var 或 filter_input 重复调用&#xff0c;我们可以使用 filter_var_array 或 the filter_input_array 函数。在本例中&#xff0c;我们使用 filter_input_array() 函数来过滤三个 GET 变量。接收到的 GET 变量是一…

c++ Qt向PHP接口POST文件流

Qt调用PHP写的接口&#xff0c;向其传递图片文件&#xff0c;并保存在服务器。 二进制文件无法直接传递&#xff0c;Qt采用Base64进行编码发送&#xff0c;PHP解码保存为文件。 注意&#xff1a;PHP收到数据之后会将POST过来的数据中的加号()替换为空格&#xff0c;造成接收到的…

在网络通讯中应用Protobuf

Protobuf的设计非常适用于在网络通讯中的数据载体&#xff0c;它序列化出来的数据量少再加上以K-V的方式来存储数据&#xff0c;对消息的版本兼容性非常强&#xff1b;还有一个比较大的优点就是有着很多的语言平台支持。下面讲解一下如何在TCP通讯应用中集成Protobuf. Protobuf…

JS中Math函数的常用方法

Math 是数学函数&#xff0c;但又属于对象数据类型 typeof Math > ‘object’ console.dir(Math) 查看Math的所有函数方法。 1&#xff0c;Math.abs() 获取绝对值 Math.abs(-12) 12 2&#xff0c;Math.ceil() and Math.floor() 向上取整和向下取整 console.log(Math.ceil(1…

C++ 泛型编程 -- 函数模版

文章目录定义声明调用方式函数模版的重载函数模版的特点工作中一个同事写了测试demo&#xff0c;想要自己尝试使用发现调用老出错&#xff0c;请教的时候发现是函数模版&#xff0c;有自己的调用方式&#xff0c;并且发现核心代码中大量的函数模版和类模版。特此做一个函数模版…

bellman_ford寻找平均权值最小的回路

给定一个有向图&#xff0c;如果存在平均值最小的回路&#xff0c;输出平均值。 使用二分法求解&#xff0c;对于一个猜测值mid&#xff0c;判断是否存在平均值小于mid的回路 如果存在平均值小于mid的包含k条边的回路&#xff0c;那么有w1w2w3...wk < k * mid,即(w1-mid)(w2…

守护进程中创建的对象php,在PHP中生成守护进程(Daemon Process)

前两天看到一篇文章《如何使用PHP编写daemon process》&#xff0c;其中对核心代码却没有细说&#xff0c;我又查了一些资料&#xff0c;还看了一本《理解Unix进程》&#xff0c;才搞明白生成守护进程的时候发生了什么。这段代码是这个样子的&#xff1a;function run(){//第一…

log4j个人使用整理

Log4j介绍&#xff1a; 略过。 配置&#xff1a; Eclipse项目中添加log4j.jar到lib下。 在bin目录下新建log4j.properties&#xff0c;编辑好log4j配置文件。 样例分析&#xff1a; 1 log4j.rootLoggerWARN, stdout, file2 log4j.appender.stdoutorg.apache.log4j.ConsoleAppen…

完全理解 Python 迭代对象、迭代器、生成器(转)

完全理解 Python 迭代对象、迭代器、生成器 本文源自RQ作者的一篇博文&#xff0c;原文是Iterables vs. Iterators vs. Generators nvie.com&#xff0c;俺写的这篇文章是按照自己的理解做的参考翻译&#xff0c;算不上是原文的中译版本&#xff0c;推荐阅读原文&#xff0c;谢…

Rocksdb 与 TitanDb 原理分析 及 性能对比测试

文章目录前言Rocksdb的compaction机制compaction作用compaction分类level style compaction&#xff08;rocksdb 默认进行的compaction策略&#xff09;level 的文件存储结构compaction过程compaction中的level target sizeuniversal style compactionfifo style compactionTit…

经典SQL练习题

题目地址&#xff1a;http://blog.csdn.net/qaz13177_58_/article/details/5575711 1、 查询Student表中的所有记录的Sname、Ssex和Class列。select sname,ssex,class from STUDENT2、 查询教师所有的单位即不重复的Depart列。select depart from TEACHER group by departselec…

php url模式在哪修改,php如何修改url

php如何修改url2020-07-03 12:15:40php修改url的方法&#xff1a;1、通过配置文件修改URL规则&#xff1b;2、设置URL伪静态&#xff0c;即限制伪静态的后缀&#xff1b;3、在配置文件中开启路由支持&#xff0c;并配置路由&#xff1b;4、将URL进行重写即可。PHP对URL设置一、…

国外十大最流行PHP框架排名

以下为十个目前最流行的基于MVC设计模式的PHP框架。1. YiiYii是一个基于组件的高性能的PHP的框架&#xff0c;用于开发大规模Web应用。Yii采用严格的OOP编写&#xff0c;并有着完善的库引用以及全面的教程。从MVC&#xff0c;DAO/ActiveRecord&#xff0c;widgets&#xff0c;c…

python_web框架

一、web框架 web框架&#xff1a; 自己完成socket的web框架&#xff1a;如&#xff0c;Tornado等由WSGI完成socket的web框架&#xff1a;如&#xff0c;Django、flash等两种实现过程&#xff1a; 第二种WSGI方式的&#xff0c;由于自带socket所以可直接写后端代码。 python标准…

g-gdb 调试多线程

代码调试工具gdb是一个能够让我们在工作中高效排查代码异常根源的利器。 在此将gdb针对多线程的调试方式做一个笔记&#xff0c;也方便后续回顾以及分享大家。 本文采用的是一个简单的多线程代码示例&#xff0c;同时调试是在mac上进行的 mac安装gdb brew install gdb即可 基…

php数据库html文本,关于php,mysql,html的数字分页和文本_php

请勿盗版&#xff0c;转载请加上出处http://blog.csdn.net/yanlintao1请勿盗版&#xff0c;转载请加上出处http://blog.csdn.net/yanlintao1首先进行样式展示希望对大家有所帮助&#xff0c;也希望大家给出意见和建议&#xff1a;第一种&#xff1a;数字分页第二种&#xff1a;…

WinDbg加载不同版本CLR

WinDbg调试.net2.0和.net4.0程序有所不同&#xff0c;因为.net4.0使用新版本的CLR。例如&#xff1a; mscoree.dll 变为 mscoree.dll 和 mscoreei.dll&#xff0c; mscorwks.dll 变为 clr.dll&#xff0c; mscorjit.dll 变为 clrjit.dll。 因此&#xff0c;在.net2.0加载mscorj…

交换机***工具——Yersinia

Yersinia是国外一款专门针对交换机执行第二层***的***工具。目前的版本是0.7.1。目前支持的操作系统及版本号如表1所示。表1 Yerdinia支持的操作系统操作系统名称版本号OpenBSD3.4 (pcap库版本至少0.7.2以上)Linux2.4.x和2.6.xSolaris5.8 64bits SPARCMac OSX10.4 Tiger (Intel…

Rocksdb 写流程,读流程,WAL文件,MANIFEST文件,ColumnFamily,Memtable,SST文件原理详解

文章目录前言Rocksdb写流程图WAL 原理分析概述文件格式查看WAL的工具创建WAL清理WALMANIFEST原理分析概述查看MANIFEST的工具创建 及 清除 MANIFEST文件内容CcolumnFamily 详解概述API介绍核心数据结构创建以及删除MEMTABLE 实现概述实现Rocksdb写入逻辑概述实现总结关于写的一…

react 入门

首先安装node.js环境 下载地址 https://nodejs.org/en/download/检查安装版本 进入命令行npm -v~~3. 安装react命令环境 npm install - g react-native-cli ~~~ 初始化项目 FirstAppreact-native init FirstApp 转载于:https://www.cnblogs.com/liu-ya/p/10511537.html

将字符串打乱输出

将字符串打乱输出 Dim i,mm,Str,StrPosition,NewStrStr  "1234567890"For i1 To Len(Str)    StrPosition  GetRandomMath(1,Len(Replace(Str,mm,"")))    Str  Replace(Str,mm,"")    mm  Mid(str,StrPosition,1)   …

php帝国系统调出图片内空,帝国CMS图集字段的大图,小图,说明的调用方法

本文实例讲述了帝国CMS图集字段的大图,小图,说明的调用方法。分享给大家供大家参考。具体方法如下&#xff1a;复制代码代码如下:$arr array();$arr $navinfor[morepic];$newarr explode(egetzy(rn),$arr);$count count(explode(egetzy(rn),$navinfor[morepic]));//图集的图…

static和global的区别

1.global在整个页面起作用。2.static只在function和class内起作用。global和$GLOBALS使用基本相同&#xff0c;但在实际开发中大不相同。global在函数产生一个指向函数外部变量的别名变量&#xff0c;而不是真正的函数外部变量&#xff0c;一但改变了别名变量的指向地址&#x…

vue 之 nextTick 与$nextTick

VUE中Vue.nextTick()和this.$nextTick()怎么使用&#xff1f; 官方文档是这样解释的&#xff1a; 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法&#xff0c;获取更新后的 DOM。 虽然 Vue.js 通常鼓励开发人员沿着“数据驱动”的方式思考&#xff…

Linux创建线程时 内存分配的那些事

文章目录问题描述问题分析针对问题1 的猜测:针对问题2 的猜测:原理追踪总结问题描述 事情开始于一段内存问题&#xff0c;通过gperf工具抓取进程运行过程中的内存占用情况。 分析结果时发现一个有趣的事情&#xff0c;top看到的实际物理内存只有几兆&#xff0c;但是pprof统计…

mysql plsql循环语句吗,Oracle PLSQL 在游标中用while循环实例程序

Oracle PLSQL 在游标中用while循环实例程序Oracle PLSQL 在游标中用while循环实例程序Oracle PLSQL 在游标中用while循环实例程序declarecursor emp_cur is select * from emp;v_emp emp%rowType;beginopen emp_cur;while emp_cur%notfound --while肯定要跟loop一起用的 且是控…