一,注释
注释就相当于一个标记,加上了标记就是给自己的程序加上了某种标记,标记可以加在
包,类,方法,字段,方法参数,局部变量上面。在java.lang中有最基本的注释类型。
在myEclipse中编写Java程序时方法的重写的注释是:@override,一旦添加这个注释,如果重写方法
是不下心写错一点,编译器是会报错的。
比如:当某个方法不建议使用,我们就可以加注释让这个方法称为一个过时方法。
@Deprecated //该注释告诉使用者这个方法已经过时了(过时了还是可以用的,API中过时的方法的原理)。
public static void sayHello() {
System.out.println("hello,黑马");
}
一个注释其实是一个类,有些过时的方法如果想取消过时的提示,可以通过@SuppressWarnings("deprecation")
取消。
@SuppressWarnings("deprecation") //这是一个注释,这个注释告诉编译器,不要提示我使用的方法过期了。
1,自定义注释:
自定义一个最简单的注释:
package cn.itheima.myday02;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
//源注释
@Retention(RetentionPolicy.RUNTIME)//源注释,这是interface的注释,告诉编译器该注释生命周期是运行时,否则则是默认编译时期
@Target({ElementType.METHOD,ElementType.TYPE}) //告诉使用该注释的程序,这个接口注释可以放在类上也可以放在方法上
public @interface MyAnnotation {
}
package cn.itheima.myday02;
@MyAnnotation//注释也是一个类
public class AnnotationTest {
public static void main(String[] args) {
//判断MyAnnotation这个注释是否存在,存在则打印出来,如果不设置MyAnnotation的源注释,那么运行时则看不到结果,因为注释默认生命周期是编译时
if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation myAnnotation = (MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);
System.out.println(myAnnotation);//@cn.itheima.myday02.MyAnnotation()
}
}
}
2,源注释:
@Retention的取值有三种,分别是:RetentionPolicy.SOURCE,RetentionPolicy.CLASS,RetentionPolicy.RUNTIME.分别对应的是Java源文件,Class文件,
运行时内存中的字节码。
@Target:设置账户是应该加在哪里,注释的位置可以使包,类,方法,字段,方法参数,局部变量。
Target的值等于ElementType.METHOD是告诉注释只可以加在方法上,如果想加在类上,可以使用数组。
{ElementType.METHOD,ElementType.TYPE} ,告诉使用该注释的程序,这个接口注释可以放在类上也可以放在方法上。
注意:使用源注释以及枚举属性值都不用死记,只要会查看API下的帮助文档,就可以了。
在java.lang.annotation包下面的类。
注释的高级应用:
因为自定义注释是在interface前面加一个@符号,然后通过@Retention和@Target设置注释的生命周期和
注释位置。注释内部的定义也是有规则的,必须是类型属性名加小括号,可以通过default关键字设置属性
的默认值。比如:String value() default "abc";在类中调用该注释的时候,需要设置属性值,然后通过
反射使用该属性的值。
注释的返回值类型可以是八种基本数据类型,Class类型,注解类型,枚举类型,以及上述这些类型的
数组类型。(参看:Java language specification)
应用示例:
1,创建的注释类
@Retention(RetentionPolicy.RUNTIME) //RetentionPolicy.RUNTIME说明一个注解的生命周期
@Target({ElementType.METHOD,ElementType.TYPE}) //告诉使用该注释的程序,这个接口注释可以放在类上也可以放在方法上
public @interface ItcastAnnotation {
String color() default "Blue"; //注释的默认值是Blue
//在注解中添加了属性,在使用这个属性的时候要为注释设置属性--->@ItcastAnnotation(color="RED")
String value();
int[] array() default {5,8,6};//返回值类型是数组类型
EnumTest.TrafficLight light() default EnumTest.TrafficLight.RED;//返回值类型是枚举类型
//添加一个返回值类型是注解类型的注解,MetaAnnotation在下面
MetaAnnotation metaAnnotation() default @MetaAnnotation("lhm");
}
//被调用的注解类
public @interface MetaAnnotation {
String value();
}
2,使用反射调用注解
@ItcastAnnotation(metaAnnotation = @MetaAnnotation("flx"),color="Red",value="abc",array={1,2,5})//数组中如果只有一个元素而已直接写数组名等于哪一个值
public class AnnotationTest {
public static void main(String[] args) {
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)) {//检查ItcastAnnotation注释是否存在
//通过反射回去自定义的注解类字节码
ItcastAnnotation annotation = (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation);//@cn.itcast.day2.ItcastAnnotation(metaAnnotation=@cn.itcast.day2.MetaAnnotation(value=flx),
//color=Red, light=RED, array=[1, 2, 5], value=abc)
//对注解的属性值的使用
System.out.println(annotation.color());//RED
System.out.println(annotation.value());//abc
System.out.println(annotation.array().length);//3
System.out.println(annotation.light().nextLight());//GREEN 默认值是RED
System.out.println(annotation.metaAnnotation().value());//flx
}
}
}
二,哈希算法补充
对于下列程序:
集合框架ArrayList和HashSet集合的比较以及hashCode()方法
ArrayList底层的数据结构是数组,可以有重复的元素,因为ArrayList集合的每个元素是有索引的,存储顺序就是按照索引顺序
存储的。HashSet集合的底层数据结构是哈希表,里面不能有重复的元素,它比较元素是不是重复的原理是通过equals方法和hashCode
方法对元素进行比较,每次添加元素时,都会查看集合中是否有这个元素,如果有就不添加,否则才添加。HashSet集合的添加元素顺序
和取出顺序是不同的。
class Point
{
public int s;
public int y;
public Point(int x,int y) {
this.x = x;
this.y = y;
}
//重写hashCode方法
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
//重写equals方法
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ReflectPoint other = (ReflectPoint) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
class ReflectTest
{
public static void main(String[] args) {
Collection collection = new HashSet();
ReflectPoint pt1 = new ReflectPoint(2,5);
ReflectPoint pt2 = new ReflectPoint(6,8);
ReflectPoint pt3 = new ReflectPoint(7,5);
ReflectPoint pt4 = new ReflectPoint(2,5);
collection.add(pt1);
collection.add(pt2);
collection.add(pt3);
collection.add(pt4);
System.out.println(collection.size());
}
}
哈希算法:当你想查找集合中是否存在某个元素的时候,通常是将这个元素与集合中的每个元素进行equals比较,如过相等
就返回结果,不相等则继续比较。但是如果有上万个元素,使用这种方法比效率就会相当低,所以有人就发明了一种哈希算法,
该算法来提高从集合中查找元素的方法,这种算法将集合分成若干个存储区域,每个对象可以算出一个哈希码,可以将哈希码
分组,每一组对别对应一个存储区域,根据哈希码就可以确定对象应该在哪个存储区域。
如果在Point类中没有重写hashCode方法,那么结果就是4,因为pt1和pt4虽然参数相同,但是属于不同的对象,
哈希值在内存中是不同的。
java中存在内存泄漏吗?存在。当我们使用的某个对象,使用完之后,程序继续往下运行,但是这个对象占用的内存空间却一直
没有被释放,这种情况就属于内存泄漏。