java知识回顾笔记(对象反射内省实例父类构造方法封装泛型super())

Posted 404.Sunflower

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java知识回顾笔记(对象反射内省实例父类构造方法封装泛型super())相关的知识,希望对你有一定的参考价值。

类&对象

在创建了一个类时,只声明但不赋值,其默认值为:

理解下图含义,即可理解对象和类:

实例

对象又被称为实例,实例变量被创建时,系统默认会赋值,例如:

Student student = new Student()
# student.name此时就有默认值

堆和栈

对象是存在堆内存中的,方法所需要的内存会在栈中分配,例如main()方法。
1.堆内存中存储对象以及实例变量
2.局部变量存放在栈里面
3.当new 一个对象时,例如Student s1=new Student()时(s1为局部变量),s1此时存储的为对象的堆地址,像s1这种存储了地址的变量有一个特殊的名字:引用

java执行堆栈画图【老杜版】

局部变量&成员变量

方法体外(class里)的变量叫成员变量、方法体内声明的变量叫局部变量
局部变量存放在栈内存中,成员变量也叫实例变量存放在堆内存

构造方法

构造方法又被称为:构造器、Constructor、构造函数
构造方法有两个作用:1.创建对象 2.给对象赋值

当new一个对象时,会自动运行一个无参数的构造方法,当用户没有自定义一个构造方法时,系统默认提供了一个无参数的构造方法

public class test 
    public static void main(String[] args)
        Student student = new Student();


Student.java

public class Student 
	String name;
    public Student()
        System.out.println("execute!!!");
    

知识回顾

封装

封装就是将public私有化

封装的主要作用:
1.保证内部结构安全
2.屏蔽复杂、暴露简单

方法名解析static

在方法体中声明的变量叫做局部变量
在方法体外声明的变量叫做成员变量
成员变量又分为:实例变量、静态变量,例如:

class VarTest
//成员变量中的实例变量,可以new对象,所以会造成空指针异常
int i;
//成员变量中的静态变量,静态的,不会需要new对象,不会造成空指针异常
static int k;

静态方法:

public static void m1()

那么我们什么时候使用static,什么时候不使用呢?根据上面提到的,成员变量中不使用static就是实例变量:

Class Chinese
//身份证应该是实例变量,因为一个身份证对应一个对象
String idCard;
//国籍,国籍是一个类别人的特性,并不属与一个人的特性
//String Contry;
Static String Contry;

如果使用非static修饰,contry每次都会在内存中开拓一片空间,导致内存浪费

如果使用static修饰,contry会存放在方法区中,不会被新建到对象中

我们可以通过Chinese.Contry来实现调用Contry,但是不能直接调用Chinese.idCard。因为Contry是被static修饰的静态变量,被static修饰的内容都可以采用类名.进行访问

Class Chinese
//身份证应该是实例变量,因为一个身份证对应一个对象
String idCard;
//国籍,国籍是一个类别人的特性,并不属与一个人的特性
//String Contry;
Static String Contry = "中国";

static: 都是修饰类相关的,所有static修饰的都可以采用类名.进行访问

反射

反射包:java.lang.refiect.*

java.lang核心包
java.util工具包
java.io io流包

反射的标志:

Class c1 = Class.forName("java.lang.String")  //c1代表了String.class文件,或者说代表了String类型

反射可以操作class文件,反射机制相关重要的类有:

java.lang.Class:代表整个字节码,代表一个类型
java.lang.reflect.Method:代表字节码中的方法字节码。代表类中的方法。
java.lang.reflect.Constructor:代表字节码中的构造方法字节码
java.lang.reflect.Field:代表字节码中的属性字节码
要先调用了Class,才能获得Method、Constructor、Field等

要操作一个类的字节码,需要首先获取到这个类的字节码,怎么获取到java.lang.Class实例?:

第一种:Class c = Class.forName(“完整类名带包名”);
第二种:Class c = 对象.getClass();
第三种:Class z =String.class; Class k =Data.class;

代码分析:
以下就是通过反射配合newInstance创建对象,c此时代表User.class这个文件或者说代表了这个类型

Class. c = Class.forName("com.test.java.bean.User");
Object obj = c.newInstance();

举例,通过反射调用runtime.exec弹计算器:

invoke是Method类中的一个方法。表示执行方法的调用
参数1.表示一个对象,要执行这个对象的方法
参数2.方法执行的参数

Runtime r = Runtime.getRuntime();
Class run = Runtime.getRuntime().getClass();
// 获取Runtime的exec方法
Method execMethod = run.getMethod("exec",String.class);
// 调用exec方法
execMethod.invoke(r,"calc");

通过反射给属性值赋值

Class c = Class.forName("com.java.test.Student"); 
Object obj = c.newInstance();
Field noFiled = c.getDeclaredField("password") //Student类中有一个String password;
noFiled.set(obj,2222)//给password设置值为2222
noFiled.get(obj)//读取password的值

//私有变量可以通过以下代码进行打破封装进行访问
noFiled.setAccessible(true)

通过反射调用指定参数类型的构造方法

Map map = TransformedMap.decorate(map, null, d);
Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
//AnnotationInvocationHandler类中有一个构造方法只接收(Class.class,Map.class)传入
Constructor ct = cls.getDeclaredConstructor(Class.class,Map.class);
ct.setAccessible(true);
//创建对象
Object o = ct.newInstance(Documented.class, map);

泛型

在下面这种情况时,it.next()该用哪种类型去接收?

使用泛型指定list中只能存储Animal类型的数据

list<Animal> myList = new ArrayList<Animal>();

因为Cat和Bird都是继承Animal的,所以这时候能够:

Cat c = new Cat();
Bird b = new Bird();
myList.add(c);
myList.add(b);

Iterator<Animal> it =myList.iterator();
while(it.hasNext())
	Animal a = it.next();
	

super()

当一个构造方法,存在super(),代表调用父类的无参构造方法,当存在super(123)表示调用父类有参数的构造方法:

class B extends A
	super();
	super(123);
	public B()
		System.out.println("B类无参构造方法!")
	

以上是关于java知识回顾笔记(对象反射内省实例父类构造方法封装泛型super())的主要内容,如果未能解决你的问题,请参考以下文章

java反射基础知识

反射笔记(转载)

JAVA反射之内省

Java反射与内省

Java 反射编程(上)

Java学习笔记:面向对象