精华内容
下载资源
问答
  • JAVA的强大之处

    千次阅读 2008-06-10 01:57:00
    图形 界面 底层之间关联 还有windows原理 内部机制如何形成 今天去头他们家给我讲 熟悉内存如何分配 文件管理 进程间还有内存是如何联系 等等都是要熟悉 打算发工资去买2本书一本是很强大的windows ...

      图形  界面 底层之间的关联  还有windows原理 内部的机制如何形成 今天去头他们家给我讲的   熟悉内存如何分配  文件管理  进程间还有内存是如何联系的 等等都是要熟悉的 打算发工资去买2本书一本是很强大的windows 的内部说明 还有就是JAX   jscript   脚本的写法  数据库的应用!保证每天11点睡觉  破解的 等等 我要做的事情还很多很多   哎  一件一件来吧  我要学习的是C++

    不是单纯的c++  要混合   好自为之吧  最好只学习一样  多了反而不hao        

    展开全文
  • /** * new String("ABC") 创建了几个对象 * new String("A"+"BC") 创建了几个对象 */ //内存中创建了2个字符串对象 //利用反射API读取 s1和strvalue属性 //开放不可见访问权限
  • 少用了一次赋值语句 所以能短下来,是内部类能直接调用外部类私有属性,打破了两个类之间调用私有属性必须使用get方法魔咒。相对应,外部类是否可以直接调用内部类私有属性???当然可以。 接口里内部...

    内部类做了什么好事?

    内部类,简单来说就是类中类,咋一看会觉得很碍眼,阻碍了我们对程序的理解,一层套一层不清爽,但出现即有道理,内部类的出现极大方便了私有属性的访问

    以实例说明,不用内部类的情况下,用两个类实现将字符串字母全变大写

    class Brim{
    	private String str = "oh hello java";
    	public String getStr() {
    		return this.str;
    	}
    	public void print() {
    		Core ce = new Core();
    		System.out.println(	ce.change(str));
    	}
    }
    
    class Core{
    	Brim bm = new Brim();
    	String str = bm.getStr();
    	public String change(String str) {
    		return str.toUpperCase();
    	}
    }
    
    public class Demo1{
    	public static void main(String[] args) {
    		Brim bm = new Brim();
    		bm.print();
    	}
    }
    

    使用内部类的情况下,将字符串字母全变成大写

    class Brim{
    	private String str = "oh hello java";
    	public void print() {
    		Core ce = new Core();
    		System.out.println(	ce.change(str));
    	}
    	class Core{
    		public String change(String str) {
    			return str.toUpperCase();
    		}
    	}
    }
    
    public class Demo1{
    	public static void main(String[] args) {
    		Brim bm = new Brim();
    		bm.print();
    	}
    }
    

    两种代码对比,使用内部类明显简短很多,那么它短在哪里?

    1. 没有使用get方法
    2. 少用了一次对象创建 Brim bm = new Brim();
    3. 少用了一次赋值语句

    之所以能短下来,是内部类能直接调用外部类的私有属性,打破了两个类之间调用私有属性必须使用get方法的魔咒。相对应的,外部类是否可以直接调用内部类的私有属性???当然可以

    接口里的内部类

    内部类不单单可以在普通类中使用,接口,抽象类,方法中都可以使用,抽其中难以理解也常用的–接口内部类讲一下。

    interface Isend{
    	public void print(Ihandle one);
    	interface Ihandle{
    		public String handle(String str);
    	}
    }
    
    class exmple implements Isend{
    	private String str = "hello java";
    	public void print(Ihandle one) {	
    		System.out.println(one.handle(str));
    	}
    	class exmpleone implements Ihandle{
    		public String handle(String str) {
    			return str.toUpperCase();
    		}
    	}
    }
    public class Demo2 {
    	public static void main(String[] args) {
    		one.print(one.new exmpleone());
    	}
    }
    
    

    这里需要注意的是接口的内部类并非一定要实现,之前也讲过的覆写的方法里参数一定要相同,可能看不懂new exmple().new exmpleone(),这表示创建内部类对象,内部类对象的创建格式一般为:

    外部类.内部类 名 = new 外部类().new 内部类();
    

    static定义的接口内部类

    interface Iuitl{
    	static interface Ihandle{
    		public String handle(String str);
    	}
    	static interface Isend{
    		public void send();
    	}
    }
    

    将一些相关接口组合,在适当的时候选择相应的接口使用,特别要注意static修饰内部接口,因此不再需要先创建外部类再进行内部类创建,用符号“.”来连接。

    class exmple implements Iuitl.Isend{
    	private String str = "hello java";
    	public void send() {	
    		System.out.println(this.str);
    	}
    }
    

    择其一继承。

    只用一次的匿名内部类

    匿名内部类最为简单,就是直接用接口抽象类创建对象并在后面跟上方法

    interface Iuitl{
    	public void send();
    }
    
    public class Demo2 {
    	public static void main(String[] args) {
    		Iuitl one  = new Iuitl() {
    			public void send() {
    				System.out.println("hello java");
    			}
    		};
    		one.send();
    	}
    }
    

    可以看到并没有使用如下代码创建子类

    class Print implements Iuitl{
    ......
    }
    

    这就是匿名内部类。🤞🤞🤞🤞🤞

    展开全文
  • 看本文前建议看下JVM篇(对类加载器详细说明):JVM学习 一、什么是注解 Annotation是从JDK5.0开始引入新技术. Annotation作用: 不是程序本身,可以对程序做出解释.(这一点和注释(comment)没什么区别) ...

    注解与反射

    **本文学自b站狂神:b站狂神–注解与反射篇**

    看本文前建议看下JVM篇(对类加载器的详细说明):JVM学习

    一、什么是注解

    • Annotation是从JDK5.0开始引入的新技术.
    • Annotation的作用:
      • 不是程序本身,可以对程序做出解释.(这一点和注释(comment)没什么区别)
      • 可以被其它程序(比如:编译器等)读取.
    • Annotation的格式:
      • 注解是以“@注释名”在代码中存在的,还可以添加一些参数值,例如:@SuppressWarnings(value=”unchecked”).
    • Annotation在哪里使用?
      • 可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息。
      • 我们可以通过反射机制编程实现对这些元素据的访问

    二、内置注解

    @Override:定义在java.lang.Override,此注解只适用于修辞方法,表示一个方法,表示一个方法声明打算重写超类种的另一个方法声明。

    @Deprecated:定义在java.lang.Deprecated中,此注解可以用于修辞方法,类,属性,表示不鼓励程序员使用这样的元素,通常是因为它很危险或者存在更好的选择。

    **@SupperessWarnings:**定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息,

    • 与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数都是已经定义好了的,我们选择性使用就好了。
    • @SuppressWarnings(“all”)
    • @SuppressWarnings(“unchecked”)
    • @SuppressWarnings(value={“unchecked”,“deprecation”})
    • 等等…

    三、元注解

    • 元注解的作用就是负责注解其它注解,Java定义了4个标准的meta-annotation类型,他们被用来对其它的anntation类型作说明
    • 这些类型和它们所支持的类在java.lang.annotation包中可以找到(@Target@Retention@Documented,@Inherited
    • @Target:用于描述注解的使用范围(即被描述的注解可以用在什么地方)
    • @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(SOURCE<CLASS<RUNTIME
    • @Document:说明该注解将包含在javadoc中
    • @Inherited:说明子类可以继承父类中的该注解
    package com.lxf.annotation;
    
    //测试元注解
    
    
    
    import java.lang.annotation.*;
    
    @MyAnnotation
    public class Test01 {
        
        @MyAnnotation
        public void test(){
            
        }
    }
    
    //定义一个注解
    //Target 表示我们的注解可以用到什么地方
    //TYPE(类),FIELD(字段), METHOD(方法),PARAMETER(参数),CONSTRUCTOR(构造函数),PACKAGE(包),
    @Target(value={ElementType.METHOD,ElementType.TYPE})
    //Retention 表示我们的注解在什么地方还有效
    //SOURCE(未编译)<CLASS(编译+未编译)<RUNTIME(运行时有效)
    @Retention(value = RetentionPolicy.RUNTIME)
    //表示是否将我们的注解生成在Javadoc中
    @Documented
    //子类可以继承父类的注解
    @Inherited
    @interface MyAnnotation{
        
    }
    

    自定义注解:

    package com.lxf.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    public class Test02 {
        @MyAnnotation2(name = "lxf", schools = {"新东方学校","北大青鸟"})
        public  void test(){
    
        }
    
        //只有一个值,可以不写对应字段
        @MyAnnotation3("张三")
        public  void test2(){
        }
    }
    
    @Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyAnnotation2{
        //注解的参数:参数类型+参数名();
        String name() default "";//如果没有默认值,我们就必须给注解下的类或方法赋值
        int age() default  0;
        int id() default -1;//如果默认值未-1,代表不存在
    
        String[] schools();
    }
    
    @Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyAnnotation3{
        String value();
    }
    

    四、反射概述

    4.1、静态VS动态语言

    动态语言

    • 是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身的结构。
    • 主要的动态语言:Object-C、C#、JavaScript、PHP、Python等。

    静态语言

    • 与动态语言相对应的,运行时结构不可变的语言就是静态语言。如:Java、C、C++。
    • Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动态性,我们可以利用反射机制获得类似动态语言的特性。Java的动态性让编程的时候更加灵活!
    4.2、反射概述
    • Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Refletion API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
    Class c=Class.forName("java.lang.String")
    
    • 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到的类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射

    正常方式:引入需要的“包类”名称–>通过new实例化–>取得实例化对象

    反射方式:实例化对象–>getClass()方法–>得到完整的“包类”名称

    4.3、java反射机制研究及应用
    • 在运行时判断一个对象所属的类
    • 在运行时构造任意一个类的对象
    • 在运行时判断任意一个类所具有的成员变量和方法
    • 在运行时获取泛型信息
    • 在运行时调用任意一个对象的成员变量和方法
    • 在运行时处理注解
    • 生成动态代理
    4.4、Java反射的优点和缺点
    • 优点:可以实现动态创建对象和编译,体现出很大的灵活性
    • 缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于直接执行相同的操作。
    4.5、反射相关的主要API
    • java.lang.Class:代表一个类
    • java.lang.reflect.Method:代表类的方法
    • java.lang.reflect.Field:代表类的成员变量
    • java.lang.reflect.Constructor:代表类的构造器
    4.6、Class类

    对象照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE都为其保留一个不变的Class类型的对象。一个Class对象包含了特定 某个结构(class/interface/enum/annotation/primitive type/void[])的有关信息。

    • Class本身也是一个类
    • Class对象只能由系统建立对象
    • 一个加载的类在JVM中只会有一个Class实例
    • 一个Class对象对应的是一个加载到JVM中的一个.class文件
    • 每个类的实例都会记得自己是由哪个Class实例所生成
    • 通过Class可以完整地得到一个类中的所有被加载的结构
    • Class类时Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象
    4.7、Class类的常用方法
    方法名 功能说明
    static ClassforName(String name) 返回指定类名name的Class对象
    Object newInstance() 调用缺省构造函数,返回Class对象的一个实例
    getName() 返回此Class对象所表示的实体(类,接口,数组类或void)的名称。
    Class getSuperClass() 返回当前Class对象的父类的Class对象
    Class[] getinterfaces() 返回当前Class对象的父类的Class对象
    ClassLoader getClassLoader() 返回该类的类加载器
    Constructor[] getConstructors() 返回一个包含某些Constructor对象的数组
    Method getMethod(String name,class… T) 返回一个Method对象,此对象的形参类型为paramType
    Field[] getDeclaredFields() 返回Field对象的一个数组
    4.8、获取Class类的实例

    a)若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高。

    Class clazz=Person.class
    

    b)已知某个类的实例,调用该实例的getClass()方法获取Class对象

    Class clazz=Person.get();
    

    c)已知一个类的全类名,且在该类的类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException

    Class clazz=Class.forName("demo01.student");
    

    d)内置基本数据类型可以直接用类名.Type

    e)还可以利用ClassLoader

    package com.lxf.reflection;
    
    public class Test03 {
        public static void main(String[] args) throws ClassNotFoundException {
            Person person=new Student();
            System.out.println("这个人是:"+person.name);
    
            //方式一:通过对象获得
            Class c1 = person.getClass();
            System.out.println(c1.hashCode());
    
            //方式二:forname获得
            Class<?> c2 = Class.forName("com.lxf.reflection.Student");
            System.out.println(c2.hashCode());
    
            //方式三:通过类名.class获得
            Class c3 = Student.class;
            System.out.println(c3.hashCode());
    
            //方式四:基本内置的属性的包装类都有一个Type属性
            Class c4 = Integer.TYPE;
            System.out.println(c4);
    
            //获得父类的类型
            Class c5 = c1.getSuperclass();
            System.out.println(c5);
        }
    }
    
    class Person{
        public String name;
    
        public Person() {
        }
    
        public Person(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    
    class Student extends Person{
        public Student(){
            this.name="学生";
        }
    }
    class Teacher extends Person{
        public Teacher(){
            this.name="老师";
        }
    }
    
    4.9、哪些类型可以有Class对象?
    • class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类。
    • interface:接口
    • []数组
    • enum:枚举
    • annotation:注解@interface
    • primitive type:基本数据类型
    • void

    练习:

    package com.lxf.reflection;
    
    import java.lang.annotation.ElementType;
    
    //所有的类型的class
    public class Test04 {
        public static void main(String[] args) {
            //类
            Class c1 = Object.class;
            //接口
            Class c2=Comparable.class;
            //一维数组
            Class c3=String[].class;
            //二维数组
            Class c4=int[][].class;
            //注解
            Class c5=Override.class;
            //枚举
            Class c6= ElementType.class;
            //基本数据类型
            Class c7=Integer.class;
            //空值类型
            Class c8=void.class;
            //
            Class c9=Class.class;
    
            System.out.println("c1="+c1);
            System.out.println("c2="+c2);
            System.out.println("c3="+c3);
            System.out.println("c4="+c4);
            System.out.println("c5="+c5);
            System.out.println("c6="+c6);
            System.out.println("c7="+c7);
            System.out.println("c8="+c8);
            System.out.println("c9="+c9);
    
            //只要元素类型与维度一样,就是同一个class
            int[] a=new int[10];
            int[] b=new int[100];
            System.out.println(a.getClass().hashCode());
            System.out.println(b.getClass().hashCode());
        }
    }
    
    

    结果:

    c1=class java.lang.Object
    c2=interface java.lang.Comparable
    c3=class [Ljava.lang.String;
    c4=class [[I
    c5=interface java.lang.Override
    c6=class java.lang.annotation.ElementType
    c7=class java.lang.Integerjava
    c8=void
    c9=class java.lang.Class
    356573597
    356573597
    

    五、Java内存分析、类的加载过程、类初始化、类加载器的作用

    5.1、java内存

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-akr95XXx-1592488733386)(E:\typoraPic\java内存.jpg)]

    5.2、类的加载过程(了解)

    当成主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xHDIsIRO-1592488733399)(E:\typoraPic\类的加载过程-1592230841454.jpg)]

    5.3、类的加载与ClassLoader的理解
    • 加载:将class文件字节码内容加载到内存中,并将这些静态数据转换为方法区的运行时结构,然后生成一个代表这个类的java.lang.Class对象.
    • 链接:将Java类的二进制代码合并到JVM的运行状态之中的过程。
      • 验证:确保加载的类信息符合JVM规范,没有安全方面的问题
      • 准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。
      • 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。
    • 初始化:
      • 执行类的构造器<clinit>()方法的过程。类构造器<clinit>()方法是由编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)。
      • 当初始化一个类的时候,如果 发现其父类还没有进行初始化,则需要先触发其父类的初始化。
      • 虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步
    package com.lxf.reflection;
    
    public class Test05 {
        public static void main(String[] args) {
            A a=new A();
            System.out.println(A.m);
            /**
             * 1.加载到内存,会产生一个对应的class对象
             * 2.链接,链接结束后m=0
             * 3.初始化
             * <clinit>(){
             * System.out.println("A类静态代码块初始化");
             *         m=300;
             *         m=100;
             * }
             * m=100
             */
        }
    }
    
    class A{
        static {
            System.out.println("A类静态代码块初始化");
            m=300;
        }
        static int m=100;
        public A(){
            System.out.println("A类的无参构造初始化");
        }
    }
    
    5.4、什么时候会发生类初始化?
    • 类的主动引用(一定会发生类的初始化)
      • 当虚拟机启动,先初始化main方法所在的类
      • new 一个类的对象
      • 调用类的静态成员(除了final常量)和静态方法
      • 使用java.lang.reflect包的方法对类进行反射调用
      • 当初始化一个类,如果其父类没有被初始化,则先会初始化它的父类
    • 类的被动引用(不会发生类的初始化)
      • 当访问一个静态域时,只有真正声明这个域的类才会被初始化。如:当通过子类引用父类的静态变量,不会导致子类初始化
      • 通过数组定义引用,不会触发此类的初始化
      • 引用常量不会触发此类的初始化(常量的链接阶段就存入调用类的常量池中了)
    package com.lxf.reflection;
    
    //测试类什么时候会初始化
    public class Test06 {
        static {
            System.out.println("Main类被加载");
        }
    
        public static void main(String[] args) throws ClassNotFoundException {
            //1.主动引用:Main类加载-->Father类被加载-->Son类被加载
            //Son son=new Son();
    
            //2.反射也会产生主动引用:Main类被加载-->Father类被加载-->Son类被加载
            //Class<?> aClass = Class.forName("com.lxf.reflection.Son");
    
            //3.不会产生类的引用的方法:
    
            //3.1、子类调用父类的静态域,Main类被加载-->父类被加载
            //System.out.println(Son.b);
    
            //3.2、类的数组定义:Main类被加载
            //Son[] array=new Son[5];
    
            //3.3、引用该类的常量:Main类被加载
            //System.out.println(Son.M);
        }
    }
    class Father{
        static   int b=2;
        static {
            System.out.println("父类被加载");
        }
    }
    
    class Son extends Father{
        static {
            System.out.println("子类被加载");
            m=300;
        }
        static int m=100;
        static final int M=1;
    }
    
    5.5、类加载器的作用
    • 类加载器的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时的数据结构,然后再在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。
    • 类缓存:标准的javaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XgvubT22-1592488733405)(E:\typoraPic\类加载器的作用.jpg)]

    • 类加载器的作用:将class文件字节码内容加载到内存中,JVM规范定义了如下类型的类的加载器。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gymgMcGv-1592488733415)(E:\typoraPic\类加载器的作用2.jpg)]

    package com.lxf.reflection;
    
    
    public class Test07 {
        public static void main(String[] args) throws ClassNotFoundException {
            //获取系统类的加载器
            ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
            System.out.println(systemClassLoader);
            //结果:sun.misc.Launcher$AppClassLoader@18b4aac2
            
            //获取系统父类加载器的父类加载器-->扩展类加载器
            ClassLoader parent = systemClassLoader.getParent();
            System.out.println(parent);
            //结果:sun.misc.Launcher$ExtClassLoader@1540e19d
            
            //获取扩展类加载器的父类加载器-->根加载器(C/C++)
            ClassLoader parent1 = parent.getParent();
            System.out.println(parent1);
            //结果:null
            
            //测试当前类是哪个加载器加载的
            ClassLoader classLoader = Class.forName("com.lxf.reflection.Test07").getClassLoader();
            System.out.println(classLoader);
            //结果:sun.misc.Launcher$AppClassLoader@18b4aac2
            
            //测试JDK内置的类是谁加载的
            ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
            System.out.println(classLoader1);
            //结果:null
    
            //如何获得系统类加载器可以加载的路径
            System.out.println(System.getProperty("java.class.path"));
            /**结果:
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\localedata.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunec.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\javaws.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfxswt.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\management-agent.jar;java
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\plugin.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;
             * C:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;
             * C:\Users\dell\IdeaProjects\20200615-注解与反射\out\production\20200615-注解与反射;
             * C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar
             */
            
            //双亲委派机制
        }
    }
    
    

    六、创建运行时类的对象

    通过反射获取运行时类的完整结构

    Field、Method、Constructor、Superclass、Interface、Annotation

    • 实现的全部接口
    • 所继承的父类
    • 全部的构造器
    • 全部的方法
    • 全部的Field
    • 注解
    • 。。。
    package com.lxf.reflection;
    
    public class Test01 {
        public static void main(String[] args) throws ClassNotFoundException {
            //通过反射获取类的class对象
            Class<?> c1 = Class.forName("com.lxf.reflection.User");
            System.out.println(c1);
    
        }
    }
    
    class User{
        private String name;//姓名
        private int id;//编号
        private int age;//年龄
    
        public User() {
        }
    
        public User(String name, int id, int age) {
            this.name = name;
            this.id = id;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", id=" + id +
                    ", age=" + age +
                    '}';
        }
    }
    
    package com.lxf.reflection;
    
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    //获得类的信息
    public class Test08 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
            Class c1 = Class.forName("com.lxf.reflection.User");
    
            //获得类的名字
            System.out.println(c1.getName());//获得包名+类名
            System.out.println(c1.getSimpleName());//获得类名
    
            System.out.println("=====================================");
    
            //获得类的属性
            //Field[] fields1 = c1.getFields();只能找到public属性
    
            Field[] fields2 = c1.getDeclaredFields();//获取全部的属性
            for (Field field : fields2) {
                System.out.println(field);
            }
    
            //获取指定属性的值
            Field name = c1.getDeclaredField("name");
            System.out.println(name);
    
            System.out.println("=====================================");
    
            //获得类的方法
            Method[] methods1 = c1.getMethods();//获得本类及其父类的全部public方法
            for (Method method : methods1) {
                System.out.println("没有加Declared:" + method);
            }
    
            Method[] methods2 = c1.getDeclaredMethods();//获得本类的所有方法
            for (Method method : methods2) {
                System.out.println("加了Declared:" + method);
            }
    
            //获得指定方法
            Method getName = c1.getMethod("getName", null);
            Method setName = c1.getMethod("setName", String.class);
            System.out.println(getName);
            System.out.println(setName);
    
            //获取指定的构造器
            System.out.println("=======================================");
            Constructor[] constructors1 = c1.getConstructors();//获得本类的所有public构造方法
            for (Constructor constructor : constructors1) {
                System.out.println("1:" + constructor);
            }
    
            Constructor[] constructors2 = c1.getDeclaredConstructors();//获得本类的所有构造方法
    
            for (Constructor constructor : constructors2) {
                System.out.println("2:" + constructor);
            }
    
            //获得指定的构造器
            Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
            System.out.println("指定:"+constructor);
            
            //getFields()与getDeclaredFields()区别:
    		//getFields()只能访问类中声明为公有的字段,私有的字段它无法访问,能访问从其它类继承来的公有方法.
    		//getDeclaredFields()能访问类中所有的字段,与public,private,protect无关,不能访问从其它类继承来的方法
    
            //getMethods()与getDeclaredMethods()区别:
            //getMethods()只能访问类中声明为公有的方法,能访问从其它类继承来的公有方法.
            //getDeclaredFields()能访问类中所有的字段,与public,private,protect无关,不能访问从其它类继承来的方法
    
            //getConstructors()与getDeclaredConstructors()区别:
            //getConstructors()只能访问类中声明为public的构造函数.
            //getDeclaredConstructors()能访问类中所有的构造函数,与public,private,protect无关
    
        }
        }
    
    

    七、有了Class对象,能做什么?

    7.1、创建类的对象:调用Class对象的newInstance()方法
    • 类必须有一个无参数的构造器
    • 类的构造器的访问权限需要足够

    思考:没有无参构造器就不能创建对象了吗?只要在操作的时候明确的调用类中的构造器,并将参数传递进去之后,才可以实例化操作。

    步骤如下:

    • 通过Class类的getDeclaredConstructor(Class…parameterTypes)取得本类的指定形参类型的构造器
    • 向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。
    • 通过Constructor实例化对象
    package com.lxf.reflection;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class Test09 {
        public static void main(String[] args) throws  Exception {
            //获得Class对象
            Class c1 = Class.forName("com.lxf.reflection.User");
    
            //构造一个对象
            //User user1 = (User) c1.newInstance();//本质是调用无参构造器,如果没有
            //System.out.println(user1);
    
            //通过构造器构造
            Constructor constructor = c1.getConstructor(String.class, int.class, int.class);
            User user2 = (User) constructor.newInstance("刘一手", 001, 18);
            System.out.println(user2);
    
            //通过反射调用普通方法
            System.out.println("=========================================");
            User user3 = (User) c1.newInstance();
            //通过反射获取一个方法
            Method setName = c1.getDeclaredMethod("setName", String.class);
            //invoke:激活的意思
            //(对象,"方法的值")
            setName.invoke(user3,"刘二手");
            System.out.println(user3);
    
            //通过反射操作属性
            System.out.println("=================================");
            User user4= (User) c1.newInstance();
            Field name = c1.getDeclaredField("name");
    
            //不能直接操作私有属性,我们需要关闭程序的安全检测,属性或者方法的setAccessible(true);
            name.setAccessible(true);//
            name.set(user4,"刘三手");
            System.out.println(user4.getName());
        }
    }
    
    
    7.2、setAccessible
    • Method和Field、Constructor对象都有setAccessible()方法。
    • setAccessible作用是启动和禁用访问安全检测的开关。
    • 参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。
      • 提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置true。
      • 使得原本无法访问的私有成员也可以访问
    • 参数值为false则指示反射的对象应该实施Java语言的访问检查
    • 开启setAccessible要比不开启setAccessible效率高几倍,而普通方式获取的对象比前者速度快上几百倍
    7.3、反射操作泛型
    • Java采用泛型擦除的机制来引入泛型,java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题,但是,一旦编译完成,所有和泛型有关的类型全部擦除
    • 为了通过反射操作这些类型,Java新增了ParameterizedType,GenericArrayType,TypeVariable和WildardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型
    • ParameterizedType:表示一种参数化类型,比如Collection<String>
    • TypeVarialbe:是各种类型变量的公共父接口
    • WildcardType:代表一种通配符类型表达式
    package com.lxf.reflection;
    
    import java.lang.reflect.Method;
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    import java.util.List;
    import java.util.Map;
    
    //通过反射获取泛型
    public class Test10 {
        public  void test01(Map<String,User> map, List<User> list){
    
        }
        public Map<String,User> test02(){
            System.out.println("test2");
            return null;
        }
    
        public static void main(String[] args) throws NoSuchMethodException {
            Method method = Test10.class.getMethod("test01", Map.class, List.class);
    
            //获取参数类型
            Type[] genericParameterTypes = method.getGenericParameterTypes();
            //遍历参数类型
            for (Type genericParameterType : genericParameterTypes) {
                System.out.println("genericParameterType = " + genericParameterType);
                //获取泛型
                if(genericParameterType instanceof ParameterizedType){
                    Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                    for (Type actualTypeArgument : actualTypeArguments) {
                        System.out.println("actualTypeArgument = " + actualTypeArgument);
                    }
                }
            }
    
    
        }
    }
    
    
    7.4、反射操作注解
    package com.lxf.reflection;
    
    import java.lang.annotation.*;
    import java.lang.reflect.Field;
    
    //练习反射操作注解
    public class Test12 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
            Class c1 = Class.forName("com.lxf.reflection.Student2");
    
            //通过反射获得注解
            Annotation[] annotations = c1.getAnnotations();
            for (Annotation annotation : annotations) {
                System.out.println("annotation = " + annotation);
            }
            //获取注解的value的值
            TableLxf tableLxf= (TableLxf) c1.getAnnotation(TableLxf.class);
            String value = tableLxf.value();
            System.out.println("value = " + value);
    
            //获得类中(此处获取字段上)指定的注解
            Field name = c1.getDeclaredField("name");
            FieldLxf annotation1 = name.getAnnotation(FieldLxf.class);
            System.out.println("annotation1-columnName = " + annotation1.columnName());
            System.out.println("annotation1-type = " + annotation1.type());
            System.out.println("annotation1-length = " + annotation1.length());
    
            Field id = c1.getDeclaredField("id");
            FieldLxf  annotation2= id.getAnnotation(FieldLxf.class);
            System.out.println("annotation2 = " + annotation2);
            System.out.println("annotation2-columnName = " + annotation2.columnName());
            System.out.println("annotation2-type = " + annotation2.type());
            System.out.println("annotation2-length = " + annotation2.length());
    
            Field age = c1.getDeclaredField("age");
            FieldLxf annotation3 = age.getAnnotation(FieldLxf.class);
            System.out.println("annotation3 = " + annotation3);
            System.out.println("annotation3-columnName = " + annotation3.columnName());
            System.out.println("annotation3-type = " + annotation3.type());
            System.out.println("annotation3-length = " + annotation3.length());
        }
    }
    
    @TableLxf("db_student")
    class Student2{
        @FieldLxf(columnName = "db_id",type = "int",length = 10)
        private int id;
        @FieldLxf(columnName = "db_age",type = "int",length = 10)
        private int age;
        @FieldLxf(columnName = "db_name",type = "varchar",length = 3)
        private String name;
    
        public Student2() {
        }
    
        public Student2(int id, int age, String name) {
            this.id = id;
            this.age = age;
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Student2{" +
                    "id=" + id +
                    ", age=" + age +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    
    
    //类名的注解
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface TableLxf{
        String value();
    }
    
    //属性的注解
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface FieldLxf{
        String columnName();
        String type();
        int length();
    }
    
    展开全文
  • java可以自动进行垃圾收集,c++需要手动释放内存,这个功能将程序员解放出来,能将更多注意力放在需要实现业务上,这也是java相对c++一个巨大优势,jvm有哪些垃圾收集算法呢? 标记清除算法:算法分为标记和...

    java可以自动进行垃圾收集,c++需要手动释放内存,这个功能将程序员解放出来,能将更多的注意力放在需要实现的业务上,这也是java相对c++的一个巨大优势,jvm有哪些垃圾收集算法呢?

    1. 标记清除算法:算法分为标记和清除两个阶段,首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象

     

    从图中可以看出这种算法的缺点在于,垃圾被回收以后造成了大量不连续的内存碎片。碎片太多可能会导致以后需要分配较大对象时,无法找到连续的足够内存从而频繁触发垃圾收集,降低系统效率。

    1. 复制算法:为了解决“标记,清除”算法的问题一种被称为复制的算法出现了,它将内存平均分为两块,每次只使用其中一块,当这一块存满时触发垃圾收集,将还存活的对象复制到另一块内存,然后将这块内存清掉,这样就不会存在内存碎片的问题。

     

     

    1. 标记整理算法:

    复制算法在存活对象较多的时候需要复制的操作也较多,最关键的是只能利用一半的内存,标记整理算法可以解决这个问题,标记整理算法中的标记和标记清除算法一样,要被回收的对象找出来以后让所有存活的对象向一端移动,然后将内存的剩余部分直接清理掉。

    1

     

    1. 分代收集算法:

    分代收集算法将内存分为新生代和老年代,新生代又分为:较大的Eden区(占80%)和两块Survivor区(各占10%),刚刚创建的对象存放在新生代的Eden区

    ,因为绝大多数的对象(98%)都是朝生夕死的,当Eden区没有足够的空间的时候虚拟机会发起一次Minor Gc,Minor Gc之后,存活对象会进入其中的一块Suvivor区,Eden区被清空,如果Suvivor区内存不够则直接进入老年代。下一次Minor Gc会将Eden和该Suvivor区的存活对象复制到另一块Suvivor区,并将Eden区和该Suvivor区清空。

    在这里我们可以看到相比复制算法,被浪费的空间只有10%。但是前提是绝大部分(90%)的对象在Mino Gc的时候会被回收,如果不满足这个条件Suvivor区大小不够,则存活的对象直接进入老年代。

    为什么需要Survivor区?

    试想一下如果没有Survior区,每次进行Minor Gc,存活的对象直接进入老年代,老年代内存被占满会发生Major Gc,Major Gc执行的速度比Minor Gc慢十倍以上,当有了Survivor区,存活的对象在两块Survior区中倒腾,当倒腾的次数达到16次说明这个对象生命力真的很顽强,才会被放入老年代。这样就减少了Major Gc发生的频次。

     

    为什么需要两块Survivor区?

    为了避免内存碎片化的问题,大家想想复制算法是如何解决标记清除算法的内存碎片化问题的,将内存分为大小相等的两块,将存活的对象复制到另一块内存,这里也是一样的道理。

     

    老年代:

    因为老年代中对象的生命力比较顽强,如果采用复制算法那些存活的对象需要被复制很多次,所以老年代采用的是标记整理算法。

     

    什么样的对象会进入老年代呢?

    1. 大对象会直接进入老年代:

    所谓的大对象就是指需要大量连续内存空间的对象,典型的大对象就是很长的字符串和数组,如果大对象直接在Eden区分配内存空间会导致Eden和Survior之间的大量内存复制,很消耗性能,所以它会直接进入老年代。

    1. 长期存活的对象会进入老年代

    所谓长期存活的对象就是前面所述,来回倒腾十六次还不死的对象。

    展开全文
  • JSP的强大之处

    2010-05-21 14:12:34
    一开始完全是用纯 java的servlet来输出页面,实现起来可以达到效果,可是代码量很大,以及可维护性都很差。   做到使用ID来查找单个用户的时候,突然陷入思考。首先要把数据库里的ID全部放入 下拉列表中,然后再...
  • java的执行原理和JVM

    2011-04-26 17:33:38
    java的执行原理和JVM,让大家更容易的了解java的内部是怎样工作的,java的强大之处有体现在哪呢。看了文档就会明白。
  • 毫无疑问程序员工作是辛苦...当成功从一段优化到极致代码中再次优化提升执行效率,得到满足感是不可取代,程序世界很单纯,付出汗水,得到回报感叹完毕,作为一个10多年IT从业者,用了差不多6年的java...
  • DWR 功能强大之处

    2010-03-20 11:24:24
    、调用没有返回值和参数的JAVA方法 1.1、dwr.xml配置 标签中包括可以暴露给javascript访问东西。 标签中指定javascript中可以访问的java类,并定义DWR应当如何获得要进行远程实例。...
  • Apache其功能强大之处在于我们可以为它开发许多模块,并作一些相应配置,从而让我们Apache服务器有更加个性化功能。1、单点登录模块LemonLDAPLemonLdap可以很棒地实现ApacheSSO功能,并且可以处理超过 20 万...
  • Java编译运行过程 初学Java最先要了解的就是Java的编译过程. ...Java的强大之处就在于只要是标准的字节码文件(.class), 就可以在不同的JVM上运行, 且效果相同. JDK Java开发工具包 JRE Java运...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,048
精华内容 419
关键字:

java的强大之处

java 订阅