黑马程序员_java内省、泛型

本文深入探讨JavaBean的概念及应用场景,介绍内省机制如何简化JavaBean的操作,并详细解析Java泛型的使用方法,包括泛型类、方法及通配符等高级特性。

------- android培训、java培训、期待与您交流! ----------

内省

JavaBean是一种特殊的java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的成员变量,且方法名符合某种命名规则。

一个类被当作JavaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。

一个符合JavaBean特点的类可以当作普通类一样使用,但把它当作JavaBean用肯定需要带来额外的好处,我们才会去了解和应用JavaBean。

优点:

1.在Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进行操作。

2.JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。用这套API操作JavaBean比用普通类的方式更方便。

示例:对JavaBean的简单内省操作。

package com.itheima;

public class Person {
	private String name;
	private int age;	
	
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
}

import java.beans.*;
import java.lang.reflect.Method;

public class IntroSpectorTest {

	public static void main(String[] args) throws Exception {
		Person p = new Person("zhangsan",20);
		String propertyName = "age";
		
		PropertyDescriptor pd = new PropertyDescriptor(propertyName,p.getClass());
		Method methodGetAge = pd.getReadMethod();
		Object retVal = methodGetAge.invoke(p);
		System.out.println(retVal);
		
		Method methodSetAge = pd.getWriteMethod();
		methodSetAge.invoke(p, 22);
		
		System.out.println(p.getAge());	
	}

}

示例:对JavaBean的复杂内省操作。

采用遍历BeanInfo的所有属性方式来查找和设置某个Person对象的age属性。

在程序中把一个类当作JavaBean来看,就是调用IntroSpector.getBeanInfo方法,得到的BeanInfo对象封装了把这个类当作JavaBean看的结果信息。

package com.itheima;

public class Person {
	private String name;
	private int age;	
	
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
}

import java.beans.*;
import java.lang.reflect.Method;

public class IntroSpectorTest {

	public static void main(String[] args) throws Exception {
		Person p = new Person("zhangsan",20);
		String propertyName = "age";
		
		BeanInfo beanInfo = Introspector.getBeanInfo(p.getClass());
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();//只能获取到JavaBean属性数组
		Object retVal = null;
		for(PropertyDescriptor pd:pds)//对数组进行迭代,获得我们需要的属性"age"。
		{
			if(pd.getName().equals(propertyName))
			{
				Method methodGetAge = pd.getReadMethod();
				retVal = methodGetAge.invoke(p);
			}
			break;
		}
		
		System.out.println(retVal);	
	}
}

BeanUtils工具包

只需要引入BeanUtils工具包,便可以轻松完成对属性的设值、获取功能。

import java.beans.*;
import org.apache.commons.beanutils.*;

public class IntroSpectorTest {

	public static void main(String[] args) throws Exception {
		Person p = new Person("zhangsan",20);
		System.out.println(BeanUtils.getProperty(p, "age"));
		BeanUtils.setProperty(p,"age","25");
		System.out.println(p.getAge());
	}

}


泛型

泛型是提供给javac编译器使用的,可以限定集合中的输出类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉“类型”信息。使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其他类型的数据。例如用反射得到集合,再调用其add方法即可。

没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储进同一个集合中。使用泛型集合,可以将一个集合中的元素限定为一个特定类型,集合只能存储同一个类型的对象,这样更安全;并且当从集合中获取一个对象时,编译器也可以知道这个对象的类型,不需要对对象进行强制类型转换,这样显得更加方便。

import java.util.ArrayList;

public class GenericTest {

	public static void main(String[] args) throws Exception{
		
		ArrayList collection1 = new ArrayList();
		collection1.add(1);
		collection1.add(1L);
		collection1.add("abc");
		
		ArrayList<String> collection2 = new ArrayList<String>();
		collection2.add("abc");
		String element = collection2.get(0);
		
		ArrayList<Integer> collection3 = new ArrayList<Integer>();
		System.out.println(collection3.getClass() == collection2.getClass());//结果显示为true,运行的时候去类型化。	
		
		collection3.getClass().getMethod("add", Object.class).invoke(collection3, "abc");//用反射得到集合,再调用其add方法
		System.out.println(collection3.get(0));
	}
}

ArrayList<E>类定义和ArrayList<Integer>类引用中涉及如下术语:

整个称为ArrayList<E>泛型类型。

ArrayList<E>中的E称为类型变量或类型参数。

整个ArrayList<Integer>称为参数化的类型。

ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数。

ArrayList<Integer>中的<>念着typeof.。

ArrayList称为原始类型。

参数化类型与原始类型的兼容性:

参数化类型可以引用一个原始类型的对象,编译报告警告,例如:

Collection<String> c = new Vector();

原始类型可以引用一个参数化类型的对象,编译报告警告,例如:

Collection c = new Vector<String>();

参数化类型不考虑类型参数的继承关系:

Vector<String> v = new Vector<Object>();//错误

Vector<Object> v = new Vector<String>();//错误

在创建数组实例时,数组的元素不能使用参数化的类型。

Vector<Integer>[] vectorList = new Vector<Integer>[10];//错误

下面的代码会报错吗?

Vector v1 = new Vector<String>();//参数化的类型赋值给原始类型,正确

Vector<Object> v = v1;//原始类型赋值给参数化了的类型,也正确

泛型中的?通配符

/*
定义一个方法,该方法用于打印出任意参数化类型的集合中的所有数据。
 */
import java.util.ArrayList;
import java.util.Collection;

public class GenericTest {

	public static void main(String[] args) throws Exception{		
		ArrayList<String> collection = new ArrayList<String>();
		collection.add("lisi");
		collection.add("zhangsan");
		collection.add("wangwu");
	
		printCollection(collection);
	}
	
	public static void printCollection(Collection<?> collection)
	{
		//collection.add(1);不能调用与参数类型有关的方法
		System.out.println(collection.size());
		for(Object obj:collection)
		{
			System.out.println(obj);
		}
	}	
}
使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。

泛型中的?通配符的扩展

限定通配符的上边界

正确:Vector<? extends Number> v = new Vector<Integer>();

错误:Vector<? extends Number> v = new Vector<String>();

限定通配符的下边界

正确:Vector<? super Integer> v = new Vector<Number>();

错误:Vector<? super Integer> v = new Vector<Byte>();

限定通配符总是包括自己。

泛型集合类的综合案例

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class GenericTest {

	public static void main(String[] args) throws Exception{
		
		HashMap<String, Integer> maps = new HashMap<String, Integer>();
		maps.put("zhangsan", 20);
		maps.put("lisi", 25);
		maps.put("wangwu", 18);
		
		Set<Map.Entry<String, Integer>> entrySet = maps.entrySet();
		for(Map.Entry<String, Integer> entry:entrySet)
		{
			System.out.println(entry.getKey() + ":" + entry.getValue());
		}
	}	
}
由C++的模板函数引入自定义泛型

 如下函数的结构很相似,仅类型不同:

int add(int x,int y){return x + y;}

float add(float x,float y){return x + y;}

double add(double x,double y){return x + y;}

C++用模板函数解决,只写一个通用的方法,它可以适用各种类型,示意代码如下:

template<class T>

T add(T x,T y){return (T)(x + y);}

Java中的泛型类似于C++中的模板,但是这种相似性仅限于表面,Java语言中的泛型基本上完全是在编译器中实现,用于编译器执行类型检查和类型推断。然后生成普通的非泛型的字节码,这种实现技术称为擦除(编译器使用泛型类型信息保证类型安全,然后生成字节码之前将其清除)。这是因为扩展虚拟机指令集来支持泛型被认为是无法接受的,这会为Java厂商升级其JVM造成难以逾越的障碍。所以,java的泛型采用了可以完全在编译器中实现的擦除方法。

交换数组中两个元素的位置的泛型方法定义如下:

public class GenericTest {

	public static void main(String[] args) throws Exception{
	
		String[] strings = new String[]{"zhangsan","lisi","wangwu"};
		swap(strings,1,2);
		for(String str:strings)
		{
			System.out.println(str);
		} 		
	}
	
	private static <T> void swap(T[] a,int i, int j)
	{
		T tmp = a[i];
		a[i] = a[j];
		a[j] = tmp;
	}
	
}
用于放置泛型的类型参数的尖括号应出现在方法的其他所有修饰符之后和在方法的返回类型之前,也就是紧邻返回值之前。按照惯例,类型参数通常用单个大写字母表示。

只有引用类型才能作为泛型方法的实际参数,swap(new int[3],3,5)语句会报告编译错误。

除了在应用泛型时可以使用extends限定符,在定义泛型时也可以使用extends限定符。

例如:Class.getAnnotation()方法的定义,并且可以用&来指定多个边界,如<V extends Serializable & cloneable> void method(){}

 普通方法、构造方法和静态方法中都可以使用泛型。编译器不允许创建类型变量的数组。

也可以用类型变量表示异常,称为参数化的异常,可以用于方法的throws列表中,但是不能用于catch语句中。

在泛型中可以同时有多个类型参数,在定义它们的尖括号中用逗号分,例如:

public static <K,V> V getValue(K key){return map.get(key);}


自定义泛型类

如果类的实例对象中的多处都要用到同一个泛型参数,即这些地方引用的泛型类型要保持同一个实际类型时,这时候就要采用泛型类型的方式进行定义,也就是类级别的泛型,语法格式如下:

public class GenericDao<T>

{

private T field;

public void save(T obj){}

public T getById(int id){}

}

import java.util.Set;

public class GenericDao<T>{
	public void add(T x)//增加
	{
		
	}

	public <T> T findById(int id)//查找
	{
		return null;
	}
	
	public void delete(T obj)//删除
	{
		
	}
	
	public void update(T obj)//更新
	{
		
	}
	
	public Set<T> findByConditions(String where)
	{
		return null;
	}
}
注意:

1.在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能使基本类型。

2.当一个变量被声明为泛型时,只能被实例变量和方法调用,而不能被静态变量和静态方法调用。因为静态成员是被所有参数化的类所共享,所以静态成员不应该有类级别的类型参数。

通过反射获得泛型的实际类型参数。

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.Vector;

public class GenericTest {
	public static void main(String[] args) throws Exception{			
		
		//用反射方式先获取到applyVector方法。
		Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
		
		//获取到该方法所有参数化类型,返回值为Type[]。
		Type[] types = applyMethod.getGenericParameterTypes();
		ParameterizedType pType = (ParameterizedType)types[0];
		
		System.out.println(pType.getRawType());
		System.out.println(pType.getActualTypeArguments()[0]);	
	}
	
	public static void applyVector(Vector<Date> v)
	{
		
	}
}

标题SpringBoot智能在线预约挂号系统研究AI更换标题第1章引言介绍智能在线预约挂号系统的研究背景、意义、国内外研究现状及论文创新点。1.1研究背景与意义阐述智能在线预约挂号系统对提升医疗服务效率的重要性。1.2国内外研究现状分析国内外智能在线预约挂号系统的研究与应用情况。1.3研究方法及创新点概述本文采用的技术路线、研究方法及主要创新点。第2章相关理论总结智能在线预约挂号系统相关理论,包括系统架构、开发技术等。2.1系统架构设计理论介绍系统架构设计的基本原则和常用方法。2.2SpringBoot开发框架理论阐述SpringBoot框架的特点、优势及其在系统开发中的应用。2.3数据库设计与管理理论介绍数据库设计原则、数据模及数据库管理系统。2.4网络安全与数据保护理论讨论网络安全威胁、数据保护技术及其在系统中的应用。第3章SpringBoot智能在线预约挂号系统设计详细介绍系统的设计方案,包括功能模块划分、数据库设计等。3.1系统功能模块设计划分系统功能模块,如用户管理、挂号管理、医生排班等。3.2数据库设计与实现设计数据库表结构,确定字段、主键及外键关系。3.3用户界面设计设计用户友好的界面,提升用户体验。3.4系统安全设计阐述系统安全策略,包括用户认证、数据加密等。第4章系统实现与测试介绍系统的实现过程,包括编码、测试及优化等。4.1系统编码实现采用SpringBoot框架进行系统编码实现。4.2系统测试方法介绍系统测试的方法、步骤及测试用例设计。4.3系统性能测试与分析对系统进行性能测试,分析测试结果并提出优化建议。4.4系统优化与改进根据测试结果对系统进行优化和改进,提升系统性能。第5章研究结果呈现系统实现后的效果,包括功能实现、性能提升等。5.1系统功能实现效果展示系统各功能模块的实现效果,如挂号成功界面等。5.2系统性能提升效果对比优化前后的系统性能
在金融行业中,对信用风险的判断是核心环节之一,其结果对机构的信贷政策和风险控制策略有直接影响。本文将围绕如何借助机器学习方法,尤其是Sklearn工具包,建立用于判断信用状况的预测系统。文中将涵盖逻辑回归、支持向量机等常见方法,并通过实际操作流程进行说明。 一、机器学习基本概念 机器学习属于人工智能的子领域,其基本理念是通过数据自动学习规律,而非依赖人工设定规则。在信贷分析中,该技术可用于挖掘历史数据中的潜在规律,进而对未来的信用表现进行预测。 二、Sklearn工具包概述 Sklearn(Scikit-learn)是Python语言中广使用的机器学习模块,提供多种数据处理和建模功能。它简化了数据清洗、特征提取、模构建、验证与优化等流程,是数据科学项目中的常用工具。 三、逻辑回归模 逻辑回归是一种常用于分任务的线性模,特别适用于二问题。在信用评估中,该模可用于判断借款人是否可能违约。其通过逻辑函数将输出映射为0到1之间的概率值,从而表示违约的可能性。 四、支持向量机模 支持向量机是一种用于监督学习的算法,适用于数据维度高、样本量小的情况。在信用分析中,该方法能够通过寻找最佳分割面,区分违约与非违约客户。通过选用不同核函数,可应对复杂的非线性关系,提升预测精度。 五、数据预处理步骤 在建模前,需对原始数据进行清理与转换,包括处理缺失值、识别异常点、标准化数值、筛选有效特征等。对于信用评分,常见的输入变量包括收入水平、负债比例、信用历史记录、职业稳定性等。预处理有助于减少噪声干扰,增强模的适应性。 六、模构建与验证 借助Sklearn,可以将数据集划分为训练集和测试集,并通过交叉验证调整参数以提升模性能。常用评估指标包括准确率、召回率、F1值以及AUC-ROC曲线。在处理不平衡数据时,更应关注模的召回率与特异性。 七、集成学习方法 为提升模预测能力,可采用集成策略,如结合多个模的预测结果。这有助于降低单一模的偏差与方差,增强整体预测的稳定性与准确性。 综上,基于机器学习的信用评估系统可通过Sklearn中的多种算法,结合合理的数据处理与模优化,实现对借款人信用状况的精准判断。在实际应用中,需持续调整模以适应市场变化,保障预测结果的长期有效性。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值