黑马程序员---Java高新技术学习笔记(后篇)

------------Android培训 、Java培训、期待与您交流----------

1.注解

相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,之后java编译器开发工具和其他程序可以用反射的方式来了解你的类及各种元素上有无何种标记,看你有什么标记就去干相应的事,标记可以加在包,类,字段,方法方法的参数以及局部变量上。注解的属性:一个注解相当于一个胸牌,其中加入各种属性加以区分。
@ITAnnotation(color = "red",value = "abc",arrayAttr={1,2,3})//如果数组arrayAttr只有一个值的话
							//可以简写成arrayAttr=1
@JavaEnhanceAnnotation(String={"abc","def","ghi","jkl"} , num = 5)
public class AnnotationTest {
	//注解的应用
	@SuppressWarnings("deprecation")
	//如果只有value属性需要设置,可以不写"value ="字段
	@ITAnnotation("uvwxyz")
	public static void main(String[] args) throws Exception
	{
		System.runFinalizersOnExit(true);//方法过时
		if(AnnotationTest.class.isAnnotationPresent(ITAnnotation.class))
		{
			
			ITAnnotation annotationTest = 
					(ITAnnotation)AnnotationTest.class.getAnnotation(ITAnnotation.class);
			System.out.println(annotationTest.color());
			System.out.println(annotationTest.value());
			System.out.println(annotationTest.arrayAttr().length);
		}
		if(AnnotationTest.class.isAnnotationPresent(JavaEnhanceAnnotation.class))
		{
			JavaEnhanceAnnotation annotationTest = 
					(JavaEnhanceAnnotation)AnnotationTest.class.getAnnotation(JavaEnhanceAnnotation.class);
			System.out.println(annotationTest.String().length);
			System.out.println(annotationTest.num());
			System.out.println(annotationTest.lamp().nextLamp().name());
		}
	}
	
	@Deprecated
	public static void sayHola()
	{
		System.out.println("lalala");
	}
	
}

元注解

根据放射测试的问题,引出@Retention(枚举类型)的三种取值:
1.RetentionPolicy.SOURCE-->java源文件
2.RetentionPolicy.CLASS-->class文件
3.RetentionPolicy.RUNTIME-->内存中的字节码

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
//Target表明注解只能放在方法以及类,接口或枚举类型的上方,别的地方无效
public @interface ITAnnotation 
{	
	//定义基本类型的属相和应用属性
	String color() default "blue";//设置ITAnnotation中的color为缺省属性
	String value();
	int[] arrayAttr() default {3,4,5};
}

2.泛型

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

ArrayList<E>类定义和ArrayList<Integer>类引用中涉及如下术语:
1.整个称为ArrayList<E>泛型类型
2.ArrayList<E>中的E称为类型变量或者类型参数
3.整个ArrayList<Integer>称为参数化的类型
4.ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数
5.ArrayList<Integer>中的<>读typeof
6.ArrayList称为原始类型

参数化类型与原始类型的兼容性
1.参数化类型可以引用一个原始类型的对象,编译报告警告
Collection<String> c = new Vector();
2.原始类型可以引用一个参数化类型的对象,编译报告警告
Collection c = new Vector<String>();
3.参数化类型不考虑类型参数的继承关系
 1.Vector<String> v = new Vector<Object>();错误,不写<Object>不会出现错误
 2.Vector<Object> v = new Vector<String>();错误
 
4.在创建数组实例时,数组的元素不能使用参数化的类型
Vector<Integer> vectorList[] = new Vector<integer>[10];
 
Vector v1 = new Vector<String>();对
Vector<Object> v = v1;对

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

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import com.intel.day01.ReflectPoint;

public class GenericTest 
{
	public static void main(String[] args) throws Exception
	{
		ArrayList collection1 = new ArrayList();
		collection1.add(1);
		collection1.add(1L);
		collection1.add("abc");
		//int i = (Integer)collection1.get(1);
		//System.out.println(i);
		
		/*================================华丽的分割线====================================*/
		
		ArrayList<String> collection2 = new ArrayList<String>();
		collection2.add("abc");
		String element = collection2.get(0);
		System.out.println(element);
		
		/*================================华丽的分割线====================================*/
		
		//泛型的应用省去了类型转换之苦
		Constructor<String> cons = String.class.getConstructor(StringBuffer.class);
		String strr = cons.newInstance(new StringBuffer("abcd"));
		System.out.println("Generic:"+strr.charAt(2));
		
		/*================================华丽的分割线====================================*/
		
		ArrayList<Integer> collection3 = new ArrayList<Integer>();
		System.out.println(collection3.getClass() == collection2.getClass());
		//collection3.add("abcde");
		collection3.getClass().getMethod("add", Object.class).invoke(collection3, "abcde");
		System.out.println("Reflect:"+collection3.get(0));
		//此代码说明泛型的定义是给编译器看的,如果按普通的add添加方法,编译无法通过。
		//但是用反射的方法,就可以跳过编译器,忽略了泛型的字节码,便可以添加其他类型的参数。
		
		/*================================华丽的分割线====================================*/
		
		//泛型中的 ? 通配符的应用和扩展,详见方法
		printCollection(collection1);
		
		/*================================华丽的分割线====================================*/
		
		//泛型&迭代==》输出集合中的键和值
		HashMap<String,Integer> maps = new HashMap<String, Integer>();
		maps.put("zxx",28);
		maps.put("xxx",27);
		maps.put("zzz",26);
		
		Set<Map.Entry<String,Integer>> entrySet = maps.entrySet();
		for(Map.Entry<String,Integer> entry : entrySet)
		{
			System.out.println(entry.getKey() + ":" + entry.getValue());
		}
		
		/*================================华丽的分割线====================================*/
		
		//自定义反省类型及其应用
		add(1,2);
		add(2.3 , 5);
		add(3 , "abc");
		add('c' , 1L);
		
		/*================================华丽的分割线====================================*/
		
		swap(new String[]{"12","23","34"},1,2);
		//swap(new int[]{1,3,5,2,4},2,4);<T>不能为基本数据类型,必须是引用类型
		
		/*================================华丽的分割线====================================*/
		
		//DAO Data Access Object数据访问对象--->用于增删改查(C.R.U.D.)
		GenericDao<ReflectPoint> dao = new GenericDao<ReflectPoint>();
		dao.add(new ReflectPoint(3, 3));
		//dao.findById(0);
		//dao.findByUserName("str");
		//dao.findByConditions("string");
		
		/*================================华丽的分割线====================================*/
		
		//通过反射获得泛型的实际参数类型
		//Vector<Date> v = new Vector<Date>();
		//System.out.println(v.getClass().getName());无法得到v的参数类型
		Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
		Type[] types = applyMethod.getGenericParameterTypes();
		ParameterizedType pType = (ParameterizedType)types[0];
		System.out.println(pType.getRawType().toString());//打印原始类型
		System.out.println(pType.getActualTypeArguments()[0]);
	}
	
	private static <T> void swap(T[] a , int i , int j)
	{
		T tmp = a[i];
		a[i] = a[j];
		a[j] = tmp;
	}

	public static void printCollection(Collection<?> collection)
	{
		//collection.add("1234");错误:因为他不知自己未来匹配的一定就是String类型
		//collection = new HashSet<Date>();//正确,因为用问号通配符定义的参数,可以指向任何类型的集合
		System.out.println("??:"+collection.size());//正确,此方法与参数类型无关
		for(Object col : collection)
		{
			System.out.println("?:"+col+"<>"+col.getClass().getName());
		}
		
		/*
		 * 限定通配符总是包括自己
		限定通配符的上界:通配符仅可以匹配Number和Number的子类
		Vector<? extends Number> x = new Vector<Integer>();//Y
		Vector<? extends Number> y = new Vector<String>();//N
		限定通配符的下界:通配符可以匹配的最低类型为integer,只能向上匹配
		Vector<? super Integer> x = new Vector<Number>();//Y
		Vector<? super Integer> x = new Vector<Byte>();//N虽然byte和integer是平级但是不行
		*/
	}
	
	private static <T> T add(T x , T y)
	{
		//return x + y;报错的原因是因为两个参数的类型不一定可以进行加法运算
		return null;
	}
	
	public static void applyVector(Vector<Date> v)
	{
		System.out.println("通过反射获得泛型的实际参数类型");
	}
}

3.类加载器

调用方法是需要用到的类,都需要通过类加载器加载进来
Java虚拟机中可以安装多个类加载器,系统默认有三个主要的类加载器,
每个类加载器负责加载特定位置的类:
BootStrap ExtClassLoader AppClassLoader

类加载器也是Java类,所以其本身也要被类加载器加载,显然必须有一个非java类的加载器BootStrap

JVM中的所以类加载器采用具有父子关系的的树形结构进行组织,在实例化每个类加载器对象时,需要
为其指定一个父级类加载器对象或者默认采用系统类加载器为其父级类加载
 
当Java虚拟机要加载一个类时,到底派哪个类去加载呢?
 1.首先,当前线程的类加载器去加载线程中的第一个类。
 2.如果类A中引用了类B。Java虚拟机将使用加载类A的类加载器来加载类B
 3.还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。

委托加载机制
每个类加载器加载类时,又先委托给其实上级类加载器,如果父级加载器已经将该类加载,则直接使用
避免了重复加载,占用内存资源
 1.当所有父级类加载器没有加载到类,回到发起者类加载器,还加载不了的话,则只能抛出
ClassNotFoundExceptipon,而不是再去找发起者类加载器的子级,因为没有getChild方法
即使有该方法,那么多儿子,也不知道该找哪一个
import java.util.Date;

public class ClassLoaderTest extends ClassLoader
{
	public static void main(String[] args) throws Exception 
	{
		System.out.println(ClassLoaderTest.class.getClassLoader().getClass().getName());
		//sun.misc.Launcher$AppClassLoader说明ClassLoader类是由AppClassLoader加载的
		System.out.println(System.class.getClassLoader());
		//null说明System类是由BootStrap加载的
		
		ClassLoader loader = ClassLoaderTest.class.getClassLoader();
		while(loader!=null)
		{
			System.out.println(loader.getClass().getName());
			loader = loader.getParent();
		}
		System.out.println(loader+" --> $BootStrap");
		/*
		sun.misc.Launcher$AppClassLoader
		sun.misc.Launcher$ExtClassLoader
		null --> $BootStrap
		*/
		
		//System.out.println(new ClassLoaderAttachment().toString());
		/*
		 * 打印结果-->Hola Maria...
		 * 如果将intellib中的加过密的class文件吧bin中正常的class文件替换掉则会出现错误
		     Exception in thread "main" java.lang.ClassFormatError: Incompatible magic 
		       value 889275713 in class file com/intel/day02/ClassLoaderAttachment
		      出现此情况下,必须用自己定义的类加载器进行解密,前提需要继承ClassLoader类
		      覆盖其findClass方法,详见MyClassLoader.java
		 */
		//打印加密后的ClassLoaderAttachment.class文件
		Class clazz = new MyClassLoader("intellib").loadClass("ClassLoaderAttachment");
		Date d1 = (Date)clazz.newInstance();
		System.out.println(d1);
	} 
}
------------Android培训 、Java培训、期待与您交流----------

好的,我会尽力回答你的问题。 曲线积分和曲面积分都是数学中的重要概念,常用于物理、工程等领域的计算和分析。 首先,让我们来了解一下曲线积分。 曲线积分是沿着一条曲线对某个向量场进行积分的过程。具体来说,设曲线C为参数方程r(t)=(x(t), y(t), z(t)), t∈[a,b],向量场F为F=(P, Q, R),则曲线积分的形式为: ∫C F·dr = ∫ab F(r(t))·r'(t) dt 其中,·表示向量的点积,r'(t)表示曲线在t时刻的切向量。 接下来,让我们了解一下曲面积分。 曲面积分是沿着一个曲面对某个向量场进行积分的过程。具体来说,设曲面S为参数方程r(u,v)=(x(u,v), y(u,v), z(u,v)),向量场F为F=(P, Q, R),则曲面积分的形式为: ∫S F·dS = ∫∫S F(r(u,v))·n(u,v) dS 其中,·表示向量的点积,n(u,v)表示曲面在(u,v)处的法向量,dS表示曲面上面积素。 在曲面积分中,常常会用到高斯公式和斯托克斯公式。 高斯公式是指对于任何一个有向光滑闭合曲面S和向量场F=(P,Q,R),都有: ∫S F·dS = ∫∫∫V div F dV 其中,div F表示向量场F的散度,V表示曲面S所围成的区域。 斯托克斯公式是指对于任何一个有向光滑曲面S和向量场F=(P,Q,R),都有: ∫S F·dr = ∫∫C curl F·n ds 其中,curl F表示向量场F的旋度,C表示曲面S的边界,n表示C的法向量,ds表示C上的弧长素。 希望这些内容能够对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值