java-反射初学(1)
来源:互联网 发布:linux查看文件多大命令 编辑:程序博客网 时间:2024/05/23 23:23
package .com;/** * * @author ManagementAndJava * *//* * 需求分析: * 1.总结常用的Eclipse快捷键 * 2.了解类在运行是的信息 * 2.1了解类的加载过程 * 2.2了解 JVM中 方法区(和其中含有的常量池) 栈区 堆区 * 3.学习反射机制; * 3.1类型信息 * 3.2反射原理 * * * 1.常用的Eclipse快捷键: * Ctrl+1: 快速修复 * Ctrl+D: 快速删除行 * Shift+Enter: 快速开启下一行 * Alt+上下键:快速移动行 * Alt+Ctrl+上下键: 快速复制行 * Ctrl+M: 放大光标所在的工作区 * Alt+/: 补全代码: * Ctrl+F11:快速运行项目 * 任意字母联想设置: * 查看快捷键: window-->Preference-->General--->Editor---Key * * * 2.了解JVM运行机制和类的运行时信息 * 2.1java内存分配分析: * JVM是java程序与操作系统之间的桥梁, * 一个完成的java程序运行时会涉及到以下内存区域:寄存器; 栈; 堆;方法区; 常量池; * 1:栈: * 保存局部变量的值:存放基本类型的变量数据,局部变量,和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象) * 或者常量池中(字符串常量对象存放在常量池中。)每个线程都有自己的栈区,数据都是私有的其他栈不能访问 * 2.堆: * 用来存放动态产生的数据,比如new产生的对象,数组。注意创建出来的对象只包含属于各自的成员变量,并不包括成员方法。 * 因为同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法,并不是每创建一个对象就把成员方 * 法复制一次;JVM只有一个堆区 被所有线程共享; * 3.方法区: * 用来存放已被加载的类的信息、常量、静态变量、即时编译器编译后的代码(在java中static的作用就是说明该变量,方法,代码块是属于 * 类的还是属于实例的)。又称为静态区,其和堆一样被所有线程共享;其存储的都是在整个线程中唯一的元素如 class 和static * 4.常量池: * JVM为每个已加载的类型维护一个常量池,常量池就是这个类型用到的常量的一个有序集合。包括直接常量(基本类型,String)和对其他类 * 型、方法、字段的符号引用(1)。池中的数据和数组一样通过索引访问。由于常量池包含了一个类型所有的对其他类型、方法、字段的符号 * 引用,所以常量池在Java的动态链接中起了核心作用。常量池存在于方法区(Method Area)内 * ( 1)、存放字符串常量和基本类型变量,比如String str=”www”; 实际上”www”是在常量池里边。 * (2)、常量池是在方法区中而不是堆内存中。 * (3)、 Java的8种基本类型(Byte, Short, Integer, Long, Character, Boolean, Float, Double), 除Float和Double以外, 其它六 * 种都实现了常量池, 但是它们只在大于等于-128并且小于等于127时才使用常量池。而如果大于127 或小于-128 则不会使用常量池 * 所以会直接在堆内存中创建对象。。 * * * 因为在java的八种基本类型: 基本类型(包装器类型) (普通变量(类)) * boolean (Boolean) char (Character) byte(Byte) short(Short) int(Integer) long(Long) float(Float) double(Double) * * *///java常量池运用如下:class ConstantPool{ /* * 在jvm规范中,每个类型 都有自己的常量池。常量池是某类型所用常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型、字段、 * 方法的符号引用。 之所以是符号引用而不是像c语言那样,编译时直接指定其他类型,是因为java是动态绑定的,只有在运行时根据某些规则才能 * 确定具体依赖的类型实例,这正是java实现多态的基础。 */ //常量池中的对象和堆中的对象 public static void method(){ Integer i1 = new Integer(1); Integer i2 = new Integer(1); //i1和i2所对应的的对象分别位于 堆中 不同的内存空间 System.out.println(i1==i2);//输出结果为 false 因为 new在堆中 引用i1和i2是在栈中存放各自堆中不同的地址 int i3 =129; int i4 = 129; //变量的符号和数据都存放在栈中 并且只会在栈中存一份数据 i5=xxff102 i6=xxff102 同时指向129 System.out.println(i3==i4);//输出结果为true;因为是在栈中只创建了一个数据两个变量符号同一个地址; /* * java中基本类型的 包装类 的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean, * 另外两种 浮点数类型(Float Double) 的包装类则没有实现。另外Byte,Short,Integer,Long,Character这5种整型 * 的包装类也只是在对应值-128-127时才可以使用常量池。 * */ //5种整形的包装类Byte,Short,Integer,Long,Character的对象, //在值小于127时可以使用常量池 Integer i5=127; Integer i6=127; //i5和i6对对应的常量127存在常量池中,并且由于常量池中数据共享,所以在常量池中只会存在一个 127;而i5和i6这两个 //变量符号是在栈中保存的(i5=xxffo12,i6=xxff012),并且指向常量池中同一个地址; System.out.println(i5==i6);//输出true //值大于127时,不会从常量池中取对象 Integer i7=128; Integer i8=128; //在堆内存中分别建立两个 128 变量符号i7和i8分别保存在栈内存中,并且指向不同的地址;i7=xxf101 i8 =xxff451; System.out.println("i7==i8"+(i7==i8));//输出false //Boolean类也实现了常量池技术 Boolean b1=true; Boolean b2=true; System.out.println("b1==b2"+(b1==b2));//输出true //浮点类型的包装类没有实现常量池技术 因此其数值保存在堆中 栈中存放对应堆中的地址; Double d1=1.0; Double d2=1.0; System.out.println("d1==d2"+(d1==d2));//输出false //String也实现了常量池技术,String类也是java中用得多的类,同样为了创建String对象的方便,也实现了常量池的技术 String s1 = "helloJava"; String s2 = "helloJava"; System.out.println("s1 == s2 "+(s1==s2));//输出结果:true String s3 = new String("hellojava"); String s4 = new String("hellojava"); //属于new对象的 对象建立在堆中 引用变量存贮在栈中 ,并且栈中引用变量存的是两个对象的地址; System.out.println("s3 == s4"+(s3=s4));//输出结果必然 为false; String s5 = "hello"; String s6 = "Java"; //String s7= s5+s6; System.out.println("s5+s6==s1"+((s5+s6)==s1));//输出结果为false;在运行时创建的字符串具有独立的内存地址, //所以不引用自同一String对象 Integer in1=30; Integer in2 =1; Integer in3 =31; System.out.println(in3==in2+in1);//输出结果为true;Java的数学计算是在内存栈里操作的其实比较的是 //基本类型(31=30+1),他们的值相同,因此结果为True。 }}class Person{//编译时其类型信息都会放入方法区 private String name;//运行时 new Person实例后 name 应有放在自己私有的栈中 ,name 对象放在堆区里 public Person(String name){ this.name =name; } public void eat(){//eat方法本身放入方法区中; System.out.println("i can eat"); }}public class ReflectTest { /* * 系统收到开始命令后,启动JVM,这个进程首先从classpath路径中找到ReflectTest.class文件,读取这个文件中的二进制 * 数据,然后将运行时的ReflectTest类的类信息存放到方法区中;(上述过程也被成为类的加载过程),紧接着JVM会从方法区 * 中找打main()方法开始执行; * */ public static void main(String[] args) { Person p1 = new Person("Mike"); /*当JVM读到这句话时,首先回去方法区中找Person的信息,由于第一次加载发现没有,此时JVM会立即加载PersonL类,并且 * 把Person类的类型信息存放在方法区中,Java虚拟机首先就是在堆区中为一个新的Person实例分配内存, 这个Person实例 * 持有着指向方法区的Person类的类型信息的引用。实际上指的是Person类的类型信息在方法区中的内存地址, 而这个地址, * 就存放了在Person实例的数据区里。 * * 在虚拟机进程中,每个线程都会拥有一个方法调用栈,用来跟踪线程运行中一系列的方法调用过程,栈中的每一个元素就被 * 称为栈帧,每当线程调用一个方法的时候就会向方法栈压入一个新帧。这里的帧用来存储方法的参数、局部变量和运算过 * 中的临时数据。 * * p1是一个在main()方法中定义的变量,可见,它是一个局部变量,因此,它被会添加到了执行main()方法的主线程的JAVA方 * 法调用栈中。而“=”将把这个p1变量指向堆区中的Person实例,也就是说,它持有了引用。 * */ p1.eat(); /* * 接下来JVM执行P1.eat()方法时,JAVA虚拟机根据局部变量p1持有的引用,定位到堆区中的Person实例,再根据Person实例持有的引用, * 定位到方法去中Person类的类型信息,从而获得eat()方法的字节码,接着执行eat()方法包含的指 令。 * */ }}
0 0
- java-反射初学(1)
- java-反射初学(2)
- Java初学习 - 反射机制1
- Java中的反射机制(初学)
- java反射初学
- java反射初学整理
- 初学java反射机制
- java 反射机制初学习
- Java反射技术初学习
- 初学Java的类加载与反射机制(一)
- 初学Java的类加载与反射机制(二)
- JAVA初学(1)
- Java初学习-Java的反射机制
- Java初学习 - 反射机制2
- 初学反射
- 初学反射
- 非常好的Java反射例子-初学反射者
- 初学Java反射之简单明了的反射例子。
- 你的系统是做什么的—用例图
- 单源最短路Bellman-Ford
- Android大神的博客
- C++变量和基本类型
- spark环境配置
- java-反射初学(1)
- 单源最短路Dijkstra
- Electron.js折腾记(一):getStart
- LeetCode刷题之旅(8)
- hdu 5677-ztr loves substring
- ACM 搜索 hdu1240 Asteroids!
- 判断有向图是否有环
- java中包及修饰符的研究与应用
- 线段树