精华内容
下载资源
问答
  • Kotlin的类 class Person { var name: String = "" var age: Int = 0 ...java类 public class Man { } 要知道获取的到底是什么,可以利用andorid stuido的类型提示,一目了然。 ...

    Kotlin的类

    class Person {
        var name: String = ""
        var age: Int = 0
        companion object {
    
        }
    }


    java类

    public class Man {
    }


    要知道获取的到底是什么,可以利用andorid stuido的类型提示,一目了然。
     

    这里写图片描述

    第二张:

    这里写图片描述


    引申

    在Java中使用Class很常见的就是,xxx类.class,比如我们在startActivity的时候startActivity(new Intent(this, OtherActivity.class)); 这里接收的就是CLass<?> cls参数。
    那么在java中获取Class的方法有哪些呢?

    1、Class c = person.getClass(); //对象获取
    2、Class cc =Person.class;//类获取
    

    而我们来看看kotlin

    //对象获取
    person.javaClass// javaClass
    person::class.java // javaClass
    //类获取
    Person::class// kClass
     person.javaClass.kotlin// kClass
    (Person::class as Any).javaClass// javaClass
    Person::class.java // javaClass
    

    哇,这么多种,他们是不是一样的,有没有什么区别?
    log看看他们到底是不是相同的Class

    println(person.javaClass == person::class.java) //true
    println(person.javaClass == Person::class.java)//true
    println(person::class.java == Person::class.java)//true
     //person.javaClass == person::class.java == Person::class.java
    println(person.javaClass == Person::class)//false
    println(person.javaClass.kotlin == Person::class)//true
    println(person::class == Person::class)//true
    

    从log来看,person.javaClass == person::class.java == Person::class.java
    三者是相同的。但是person.javaClass == Person::class却是不同的。为什么呢?

    原因是在kotlin中的Class与Java不同,kotlin中有一个自己的Class叫做KClassperson::class 和Person::class都是获取kotlin的KClass,所以println(person::class == Person::class) 为true。
    我们可以从kotlin的KClass获取到java的Class,person::class.java就是如此,先获取到kotlin的KClass然后再获取javaClass。
    object/class->kClass->Class
    同样也可以通过java的Class获取kotlin的KClass,person.javaClass.kotlin就是先获取javaClass然后再获取kotlin的KClass
    object/class->Class->KClass
    那么KClass都有些什么用呢?Find Usages 可以看到


    几乎多数跟Reflect相关,而用的最多的也是在KClasses里面
    KClasses扩展了许多跟反射相关的方法,算的上是kotlin的反射中类主力输出。



    如果要使用kotlin的反射类的话,要加入

      compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
    

    举个例子

    我们要把一个类的所有字段通过反射给打印出来,调用java的方法来实现是这样

     println (Person::class.java.declaredFields.map {
                it.isAccessible = true
                "${it.name}: ${it.get(person)}"
            }.joinToString(","))
    

    我们通过Person::class拿到KClass,然后.java拿到java的Class<?>,再获取declaredFields,最后通过map,然后把获取的Field获取到值打印出来

    问题

    而使用kotlin,我们还有别的做法

     println (Person::class.memberProperties.map {
                it.isAccessible = true
                "${it.name}: ${it.get(person)}"
            }.joinToString(","))
    

    通过Person::class拿到KClass,直接调用KClass的memberProperties来拿到KProperty的Collection集合,然后进行操作。当然,这里KProperty也是kotlin的反射类中的,也类似于Java的Field。
    那么既然可以这样,理论上这样也应该是可以的

    //person是对象不是Person类
     println (person::class.memberProperties.map {
                it.isAccessible = true
                "${it.name}: ${it.get(person)}"
            }.joinToString(","))
    

    这下却出错了,真的奇怪!

    Error:(73, 31) Out-projected type 'KProperty1<out OtherActivity.Person, Any?>' prohibits the use of 'public abstract fun get(receiver: T): R defined in kotlin.reflect.KProperty1'
    

    为什么会这样?

    查看it发现

    kotlin的property的Person为out逆变的,R只能作为输出,不能作为get的参数传入,所报错了。
    这里的kotlin泛型还是有点小坑的需要你踩一踩,网上有一篇文章解释说明了一番

    那么怎么改呢?三种办法:

    第一种:

    //扩展KProperty的get方法为getUnsafed,其实就是去掉了out
       fun <T, R> KProperty1<T, R>.getUnsafed(receiver: Any): R {
            return get(receiver as T)
        }
    //然后
    println(person::class.memberProperties.map {
                it.isAccessible = true
                "${it.name}: ${it.getUnsafed(person)}"
            }.joinToString(","))
    

    第二种:

    //强转一下
     println(person::class.memberProperties.map {
                it.isAccessible = true
                it as KProperty1<Person, Any>
                "${it.name}: ${it.get(person)}"
            }.joinToString(","))
    

    第三种:

    //这一种就涉及到kotlin中的获取KClass的方式, 先获取java的Class再获取kotlin的KClass
    //神奇的是,这种获取到的it的类型没有out,而是我们期望的 KProperty1<Person, Any>
     println(person.javaClass.kotlin.memberProperties.map {
                it.isAccessible = true
                "${it.name}: ${it.get(person)}"
            }.joinToString(","))
    


    摘自:链接:https://www.jianshu.com/p/a900ee71ae7f
     

     

    展开全文
  • kotlin反射class.java和javaClass区别

    千次阅读 2017-12-28 19:51:27
    kotlin反射class.java和javaClass区别kotlin文件的类class Person { var name: String = "" var age: Int = 0 } java文件的类public class Cat {}测试代码:fun main(args: Array) { val person = Person() val

    kotlin反射class.java和javaClass区别

    kotlin文件的类

    class Person {
        var name: String = ""
        var age: Int = 0
    }
    

    java文件的类

    public class Cat {
    
    }
    
    

    测试代码:

    fun main(args: Array<String>) {
        val person = Person()
        val cat = Cat()
        println("person::class=${person::class}")//得到的是KClass<Person>和Person::class一样
        println("person::class.java=${person::class.java}")//得到的是Class<Person>对象
        println("person::javaClass=${person::javaClass}")//未知?
        println("person.javaClass.kotlin=${person.javaClass.kotlin}")//得到的是Class<Person>对象
        println("cat.javaClass.kotlin=${cat.javaClass.kotlin}")//拿到的是KClass
        println("Cat::class.java=${Cat::class.java}")//得到的Class<Cat>
        println("cat.javaClass == Cat::class.java=${cat.javaClass == Cat::class.java}")//Class<Cat>==Class<Cat>
        println("person.javaClass == Person::class.java=${person.javaClass == Person::class.java}")//Class<Person>==Class<Person>
        println("person.javaClass.kotlin == Person::class=${person.javaClass.kotlin == Person::class}")//KClass<Person>==KClass<Person>
        println("cat.javaClass.kotlin == Cat::class=${cat.javaClass.kotlin == Cat::class}")//KClass<Cat>==KClass<Cat>
    }
    

    输出结果:

    person::class=class Person (Kotlin reflection is not available)
    person::class.java=class Person
    person::javaClass=property javaClass (Kotlin reflection is not available)
    person.javaClass.kotlin=class Person (Kotlin reflection is not available)
    cat.javaClass.kotlin=class Cat (Kotlin reflection is not available)
    Cat::class.java=class Cat
    cat.javaClass == Cat::class.java=true
    person.javaClass == Person::class.java=true
    person.javaClass.kotlin == Person::class=true
    cat.javaClass.kotlin == Cat::class=true
    
    Process finished with exit code 0
    

    总结:
    Cat::class.java和cat.javaClass都表示Class
    person.javaClass.kotlin == Person::class都表示KClass

    展开全文
  • JAVA class文件中的符号引用

    万次阅读 2014-01-02 10:36:00
    在编译的时候,class文件中是通过叫做"符号引用"的方式来实现的。 如下面的例子 public interface Intf {   public static String str = "abcde";  public static int ival = new Random().nex
    在java代码中,一个类可能使用另外类或者接口的字段或者调用另外一个类的方法。
    
    在编译的时候,class文件中是通过叫做"符号引用"的方式来实现的。
    如下面的例子
    public interface Intf {    
        public static String str = "abcde";
        public static int ival = new Random().nextInt();

    }
    public class T {
        public static int tint = Intf.ival;
    }
    class T编译成class 文件之后,利用javap -verbose 查看class文件,可以看到
    在初始化static int tint的时候,从常量池的第12项取值
    static {};
      Code:
       Stack=1, Locals=0, Args_size=0
       0:    getstatic    #12; //Field Intf.ival:I
       3:    putstatic    #17; //Field tint:I
       6:    return
      LineNumberTable:
       line 6: 0
       line 3: 6
    常量池的第12项是一个符号引用,指向Intf的ival字段。ival的值只能在运行的时候才能确定。
    const #12 = Field    #13.#15;    //  Intf.ival:I
    const #13 = class    #14;    //  Intf
    在运行的时候会将符号引用解析为指向Intf内存地址的直接引用。

    如果将class T改为如下,引用的是Intf的一个在编译时候就可以确定的常量值。
    通过查看编译后的class文件,发现在T的class文件中,是将str = "abcde";的值
    "abcde"直接复制了一份放到了常量池中,没有符号引用。
    public class T {
        public static String tstr = Intf.str;
    }
    在初始化static int tint的时候,从常量池的第12项取值
    static {};
      Code:
       Stack=1, Locals=0, Args_size=0
       0:    ldc    #12; //String abcde
       2:    putstatic    #14; //Field tstr:Ljava/lang/String;
       5:    return
      LineNumberTable:
       line 5: 0
       line 3: 5
    常量池的第12项直接为"abcde"字符串。
    const #12 = String    #13;    //  abcde
    const #13 = Asciz    abcde;

    本文的测试是在SUN 的hotspot jvm环境中。

    后面这种情况在classpath中甚至可以没有Intf类文件。

    展开全文
  • JavaClass对象详解

    万次阅读 多人点赞 2018-06-01 14:50:40
    从某种意义上来说,java有两种对象:实例对象和Class对象。每个类的运行时的类型信息就是用Class对象表示的。它包含了与类有关的信息。其实我们的实例对象就通过Class对象来创建的。Java使用Class对象执行其RT...

    https://blog.csdn.net/mcryeasy/article/details/52344729

    待优化整理 总结

    Class类简介

      在java世界里,一切皆对象。从某种意义上来说,java有两种对象:实例对象和Class对象。每个类的运行时的类型信息就是用Class对象表示的。它包含了与类有关的信息。其实我们的实例对象就通过Class对象来创建的。Java使用Class对象执行其RTTI(运行时类型识别,Run-Time Type Identification),多态是基于RTTI实现的。

      每一个类都有一个Class对象,每当编译一个新类就产生一个Class对象,基本类型 (boolean, byte, char, short, int, long, float, and double)有Class对象,数组有Class对象,就连关键字void也有Class对象(void.class)。Class对象对应着java.lang.Class类,如果说类是对象抽象和集合的话,那么Class类就是对类的抽象和集合。

      Class类没有公共的构造方法,Class对象是在类加载的时候由Java虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。一个类被加载到内存并供我们使用需要经历如下三个阶段:

    1. 加载,这是由类加载器(ClassLoader)执行的。通过一个类的全限定名来获取其定义的二进制字节流(Class字节码),将这个字节流所代表的静态存储结构转化为方法去的运行时数据接口,根据字节码在java堆中生成一个代表这个类的java.lang.Class对象。

    2. 链接。在链接阶段将验证Class文件中的字节流包含的信息是否符合当前虚拟机的要求,为静态域分配存储空间并设置类变量的初始值(默认的零值),并且如果必需的话,将常量池中的符号引用转化为直接引用。

    3. 初始化。到了此阶段,才真正开始执行类中定义的java程序代码。用于执行该类的静态初始器和静态初始块,如果该类有父类的话,则优先对其父类进行初始化。

      
      所有的类都是在对其第一次使用时,动态加载到JVM中的(懒加载)。当程序创建第一个对类的静态成员的引用时,就会加载这个类。使用new创建类对象的时候也会被当作对类的静态成员的引用。因此java程序程序在它开始运行之前并非被完全加载,其各个类都是在必需时才加载的。这一点与许多传统语言都不同。动态加载使能的行为,在诸如C++这样的静态加载语言中是很难或者根本不可能复制的。

      在类加载阶段,类加载器首先检查这个类的Class对象是否已经被加载。如果尚未加载,默认的类加载器就会根据类的全限定名查找.class文件。在这个类的字节码被加载时,它们会接受验证,以确保其没有被破坏,并且不包含不良java代码。一旦某个类的Class对象被载入内存,我们就可以它来创建这个类的所有对象。


    如何获得Class对象

    有三种获得Class对象的方式:

    1. Class.forName(“类的全限定名”)
    2. 实例对象.getClass()
    3. 类名.class (类字面常量)

    Class.forName 和getClass()

    我们先看看如下的例子:

    package com.cry;
    class Dog {
        static {
            System.out.println("Loading Dog");
        }
    }
    class Cat {
        static {
            System.out.println("Loading Cat");
        }
    }
    public class Test {
        public static void main(String[] args){
            System.out.println("inside main");
            new Dog();
            System.out.println("after creating Dog");
            try {
                Class cat=Class.forName("com.cry.Cat");
            } catch (ClassNotFoundException e) {
                System.out.println("Couldn't find Cat");
            }
            System.out.println("finish main");
        }
    }
    /* Output:
        inside main
        Loading Dog
        after creating Dog
        Loading Cat
        finish main
     */
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

      上面的Dog、Cat类中都有一个静态语句块,该语句块在类第一次被加载时候被执行。这时会有相应的信息打印出来,告诉我们这个类什么时候被加载了。从输出中可以看到,Class对象仅在需要的时候才被加载,static初始化是在类加载时进行的。

      Class.forName方法是Class类的一个静态成员。forName在执行的过程中发现如果类Dog还没有被加载,那么JVM就会调用类加载器去加载Dog类,并返回加载后的Class对象。Class对象和其他对象一样,我们可以获取并操作它的引用。在类加载的过程中,Dog类的静态语句块会被执行。如果Class .forName找不到你要加载的类,它会抛出ClassNotFoundException异常。

      Class.forName的好处就在于,不需要为了获得Class引用而持有该类型的对象,只要通过全限定名就可以返回该类型的一个Class引用。如果你已经有了该类型的对象,那么我们就可以通过调用getClass()方法来获取Class引用了,这个方法属于根类Object的一部分,它返回的是表示该对象的实际类型的Class引用:

    package com.cry;
    class Dog {
        static {
            System.out.println("Loading Dog");
        }
    }
    public class Test {
        public static void main(String[] args) {
            System.out.println("inside main");
            Dog d = new Dog();
            System.out.println("after creating Dog");
            Class c = d.getClass();
            System.out.println("finish main");
        }
    }
    /* Output:
        inside main
        Loading Dog
        after creating Dog
        finish main
     */
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    利用new操作符创建对象后,类已经装载到内存中了,所以执行getClass()方法的时候,就不会再去执行类加载的操作了,而是直接从java堆中返回该类型的Class引用。

    类字面常量

      java还提供了另一种方法来生成对Class对象的引用。即使用类字面常量,就像这样:Cat.class,这样做不仅更简单,而且更安全,因为它在编译时就会受到检查(因此不需要置于try语句块中)。并且根除了对forName()方法的调用,所有也更高效。类字面量不仅可以应用于普通的类,也可以应用于接口、数组及基本数据类型。

    注意:基本数据类型的Class对象和包装类的Class对象是不一样的:

    Class c1 = Integer.class;
    Class c2 = int.class;
    System.out.println(c1);
    System.out.println(c2);
    System.out.println(c1 == c2);
    /* Output
    class java.lang.Integer
    int
    false
    */
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    但是在包装类中有个一个字段TYPE,TYPE字段是一个引用,指向对应的基本数据类型的Class对象,如下所示,左右两边相互等价: 
    这里写图片描述 
      
      用.class来创建对Class对象的引用时,不会自动地初始化该Class对象(这点和Class.forName方法不同)。类对象的初始化阶段被延迟到了对静态方法或者非常数静态域首次引用时才执行:

    package com.cry;
    class Dog {
        static final String s1 = "Dog_s1";
        static  String s2 = "Dog_s2";
        static {
            System.out.println("Loading Dog");
        }
    }
    class Cat {
        static String s1 = "Cat_s1";
        static {
            System.out.println("Loading Cat");
        }
    }
    public class Test {
        public static void main(String[] args) throws ClassNotFoundException {
            System.out.println("----Star Dog----");
            Class dog = Dog.class;
            System.out.println("------");
            System.out.println(Dog.s1);
            System.out.println("------");
            System.out.println(Dog.s2);
            System.out.println("---start Cat---");
            Class cat = Class.forName("com.cry.Cat");
            System.out.println("-------");
            System.out.println(Cat.s1);
            System.out.println("finish main");
        }
    }
    /* Output:
    ----Star Dog----
    ------
    Dog_s1
    ------
    Loading Dog
    Dog_s2
    ---start Cat---
    Loading Cat
    -------
    Cat_s1
    finish main
     */
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

      从上面我们可以看到,如果仅使用.class语法来获得对类的Class引用是不会引发初始化的。但是如果使用Class.forName来产生引用,就会立即进行了初始化,就像Cat所看到的。

      如果一个字段被static final修饰,我们称为”编译时常量“,就像Dog的s1字段那样,那么在调用这个字段的时候是不会对Dog类进行初始化的。因为被static和final修饰的字段,在编译期就把结果放入了常量池中了。但是,如果只是将一个域设置为static 或final的,还不足以确保这种行为,就如调用Dog的s2字段后,会强制Dog进行类的初始化,因为s2字段不是一个编译时常量。

    通过javap -c -v对Dog的字节码进行反汇编:

    {
      static final java.lang.String s1;
        flags: ACC_STATIC, ACC_FINAL
        ConstantValue: String Dog_s1
      static java.lang.String s2;
        flags: ACC_STATIC
      com.cry.Dog();
        flags:
        Code:
          stack=1, locals=1, args_size=1
             0: aload_0
             1: invokespecial #1                  // Method java/lang/Object."<init>":()V
             4: return
          LineNumberTable:
            line 3: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0       5     0  this   Lcom/cry/Dog;
      static {};
        flags: ACC_STATIC
        Code:
          stack=2, locals=0, args_size=0
             0: ldc           #2                  // String Dog_s2
             2: putstatic     #3                  // Field s2:Ljava/lang/String;
             5: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
             8: ldc           #5                  // String Loading Dog
            10: invokevirtual #6                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
            13: return
          LineNumberTable:
            line 6: 0
            line 9: 5
            line 10: 13
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

      从上面可以看出s1在编译后被ConstantValue属性修饰 ConstantValue: String Dog_s1,表示即同时被final和static修饰。而s2并没有被ConstantValue修饰,因为它不是一个编译时常量。在static{}中表示类的初始化操作,在操作中我们看到只有s2字段进行了赋值,而却没有s1的踪影,因此调用s1字段是不会触发类的初始化的。

    小结

      一旦类被加载了到了内存中,那么不论通过哪种方式获得该类的Class对象,它们返回的都是指向同一个java堆地址上的Class引用。jvm不会创建两个相同类型的Class对象:

    package com.cry;
    class Cat {
        static {
            System.out.println("Loading Cat");
        }
    }
    public class Test {
        public static void main(String[] args) throws ClassNotFoundException {
            System.out.println("inside main");
            Class c1 = Cat.class;
            Class c2= Class.forName("com.cry.Cat");
            Class c3=new Cat().getClass();
            Class c4 =new Cat().getClass();
            System.out.println(c1==c2);
            System.out.println(c2==c3);
            System.out.println("finish main");
        }
    }
    /* Output:
    inside main
    -------
    Loading Cat
    true
    true
    finish main
     */
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    从上面我们可以看出执行不同获取Class引用的方法,返回的其实都是同一个Class对象。

      其实对于任意一个Class对象,都需要由它的类加载器和这个类本身一同确定其在就Java虚拟机中的唯一性,也就是说,即使两个Class对象来源于同一个Class文件,只要加载它们的类加载器不同,那这两个Class对象就必定不相等。这里的“相等”包括了代表类的Class对象的equals()、isAssignableFrom()、isInstance()等方法的返回结果,也包括了使用instanceof关键字对对象所属关系的判定结果。所以在java虚拟机中使用双亲委派模型来组织类加载器之间的关系,来保证Class对象的唯一性。


    泛型Class引用

      Class引用表示的就是它所指向的对象的确切类型,而该对象便是Class类的一个对象。在JavaSE5中,允许你对Class引用所指向的Class对象的类型进行限定,也就是说你可以对Class对象使用泛型语法。通过泛型语法,可以让编译器强制指向额外的类型检查:

    public final class Class<T> implements java.io.Serializable,
                                  GenericDeclaration,
                                  Type,
                                  AnnotatedElement {
    • 1
    • 2
    • 3
    • 4
       Class<Integer> c1 = int.class;
       c1=Integer.class;
       //c1=Double.class; 编译报错
    • 1
    • 2
    • 3

    虽然int.class和Integer.class指向的不是同一个Class对象引用,但是它们基本类型和包装类的关系,int可以自动包装为Integer,所以编译器可以编译通过。

    泛型中的类型可以持有其子类的引用吗?不行:

    Class<Number> c1 = Integer.class;  //编译报错
    • 1

    虽然Integer继承自Number,但是编译器无法编译通过。

    为了使用泛化的Class引用放松限制,我们还可以使用通配符,它是Java泛型的一部分。通配符的符合是”?“,表示“任何事物“:

     Class<?> c1 = int.class;
      c1= double.class;
    • 1
    • 2

    Class

            Class<? extends Number> c1 = Integer.class;
            c1 = Number.class;
            c1 = Double.class;
            // c1=String.class; 报错,不属于Number类和其子类
    • 1
    • 2
    • 3
    • 4

    通配符?不仅可以与extend结合,而且还可以与super关键字相结合,表示被限定为某种类型,或该类型的任何父类型:

            Class<? super Integer> c1 = Integer.class;
            c1 = Number.class;
            c1 = Object.class;
            c1=Integer.class.getSuperclass();
    • 1
    • 2
    • 3
    • 4

    向Class引用添加泛型语法的原因仅仅是为了提供编译期类型检查。


    Class类的方法

    方法名说明
    forName()(1)获取Class对象的一个引用,但引用的类还没有加载(该类的第一个对象没有生成)就加载了这个类。
    (2)为了产生Class引用,forName()立即就进行了初始化。
    Object-getClass()获取Class对象的一个引用,返回表示该对象的实际类型的Class引用。
    getName()取全限定的类名(包括包名),即类的完整名字。
    getSimpleName()获取类名(不包括包名)
    getCanonicalName()获取全限定的类名(包括包名)
    isInterface()判断Class对象是否是表示一个接口
    getInterfaces()返回Class对象数组,表示Class对象所引用的类所实现的所有接口。
    getSupercalss()返回Class对象,表示Class对象所引用的类所继承的直接基类。应用该方法可在运行时发现一个对象完整的继承结构。
    newInstance()返回一个Oject对象,是实现“虚拟构造器”的一种途径。使用该方法创建的类,必须带有无参的构造器
    getFields()获得某个类的所有的公共(public)的字段,包括继承自父类的所有公共字段。 类似的还有getMethods和getConstructors。
    getDeclaredFields获得某个类的自己声明的字段,即包括public、private和proteced,默认但是不包括父类声明的任何字段。类似的还有getDeclaredMethods和getDeclaredConstructors。

    package com.cry;
    import java.lang.reflect.Field;
    interface I1 {
    }
    interface I2 {
    }
    class Cell{
        public int mCellPublic;
    }
    class Animal extends  Cell{
        private int mAnimalPrivate;
        protected int mAnimalProtected;
        int mAnimalDefault;
        public int mAnimalPublic;
        private static int sAnimalPrivate;
        protected static int sAnimalProtected;
        static int sAnimalDefault;
        public static int sAnimalPublic;
    }
    class Dog extends Animal implements I1, I2 {
        private int mDogPrivate;
        public int mDogPublic;
        protected int mDogProtected;
        private int mDogDefault;
        private static int sDogPrivate;
        protected static int sDogProtected;
        static int sDogDefault;
        public static int sDogPublic;
    }
    public class Test {
        public static void main(String[] args) throws IllegalAccessException, InstantiationException {
            Class<Dog> dog = Dog.class;
            //类名打印
            System.out.println(dog.getName()); //com.cry.Dog
            System.out.println(dog.getSimpleName()); //Dog
            System.out.println(dog.getCanonicalName());//com.cry.Dog
            //接口
            System.out.println(dog.isInterface()); //false
            for (Class iI : dog.getInterfaces()) {
                System.out.println(iI);
            }
             /*
              interface com.cry.I1
              interface com.cry.I2
             */
    
            //父类
            System.out.println(dog.getSuperclass());//class com.cry.Animal
            //创建对象
            Dog d = dog.newInstance();
            //字段
            for (Field f : dog.getFields()) {
                System.out.println(f.getName());
            }
            /*
                mDogPublic
                sDogPublic
                mAnimalPublic
                sAnimalPublic
                mCellPublic  //父类的父类的公共字段也打印出来了
             */
            System.out.println("---------");
            for (Field f : dog.getDeclaredFields()) {
                System.out.println(f.getName());
            }
            /** 只有自己类声明的字段
             mDogPrivate
             mDogPublic
             mDogProtected
             mDogDefault
             sDogPrivate
             sDogProtected
             sDogDefault
             sDogPublic
             */
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    getName、getCanonicalName与getSimpleName的区别:

    getSimpleName:只获取类名 
    getName:类的全限定名,jvm中Class的表示,可以用于动态加载Class对象,例如Class.forName。 
    getCanonicalName:返回更容易理解的表示,主要用于输出(toString)或log打印,大多数情况下和getName一样,但是在内部类、数组等类型的表示形式就不同了。

    package com.cry;
    public class Test {
        private  class inner{
        }
        public static void main(String[] args) throws ClassNotFoundException {
            //普通类
            System.out.println(Test.class.getSimpleName()); //Test
            System.out.println(Test.class.getName()); //com.cry.Test
            System.out.println(Test.class.getCanonicalName()); //com.cry.Test
            //内部类
            System.out.println(inner.class.getSimpleName()); //inner
            System.out.println(inner.class.getName()); //com.cry.Test$inner
            System.out.println(inner.class.getCanonicalName()); //com.cry.Test.inner
            //数组
            System.out.println(args.getClass().getSimpleName()); //String[]
            System.out.println(args.getClass().getName()); //[Ljava.lang.String;
            System.out.println(args.getClass().getCanonicalName()); //java.lang.String[]
            //我们不能用getCanonicalName去加载类对象,必须用getName
            //Class.forName(inner.class.getCanonicalName()); 报错
            Class.forName(inner.class.getName());
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    参考: 
    java中的Class对象和new关键字解析 
    Thinking in Java


    展开全文
  • Java Class类简介

    万次阅读 2011-01-22 17:48:00
    class类的实例表示java应用运行时的类(class ans enum)或接口(interface and annotation)(每个java类运行时都在JVM里表现为一个class对象,可通过类名.class,类型.getClass(),Class.forName("类名")等方法...
  • java调用class文件

    千次阅读 2019-11-13 22:24:38
    使用java调用class文件有两种情况 1、class没有package 比如有个class文件HelloWord.classjava命令调用 java HelloWorld 这里后面不要加class后缀 2、class有package 1、 比如类名为str.Test1 结构为 ...
  • Java通过Class的对象来获取泛型的class示例
  • @[TOC](解决 java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer (java.lang.String and java.lang.Integer are in module java.base of loader ‘bootstrap’)) ...
  • javaclass文件批量反编译成java

    万次阅读 多人点赞 2018-05-14 15:42:49
    近来刚做完项目闲来无事就研究起了反编译,之前做一个orc识别vin码功能在度娘出来的全是那几家...class文件是java文件编译后产生的一个文件,class文件便于在软件上运行,但是我们无法阅读中间的程序,所以我们需...
  • java修改class文件指定内容

    万次阅读 2018-04-07 17:10:14
    java 中可以直接修改class文件,而不用反编译,方法如下: import java.io.DataInput; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; ...
  • javaClass对象详解

    万次阅读 多人点赞 2012-02-09 08:15:35
    java中把生成Class对象和实例对象弄混了,更何况生成Class对象和生成instance都有多种方式。所以只有弄清其中的原理,才可以深入理解。首先要生成Class对象,然后再生成Instance。那Class对象的生成方式有哪些呢,...
  • JAVA中类的public classclass的区别详解

    万次阅读 多人点赞 2017-05-10 11:48:20
    为了控制某个类的访问权限,修饰词必须出现在关键字class之前。例如:public class Student {} 在编写类的时候可以使用两种方式定义类: (A)public class定义类 (B)class定义类 2.public class定义类 ...
  • Java之public classclass声明区别

    万次阅读 2017-01-10 09:36:18
    Java之public classclass声明区别
  • 深入理解Java类型信息(Class对象)与反射机制

    万次阅读 多人点赞 2017-05-01 23:19:19
    【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) ...深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解
  • java加密class和解密class加载运行

    千次阅读 2012-06-11 14:49:18
    import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream;
  • Java .class文件是什么?

    千次阅读 2015-06-09 17:21:28
    Java class文件是什么?   java class 文件是对Java程序二进制文件格式的精确定义。每一个Java class文件都对一个Java类或者Java接口做出了全面描述。一个class文件中只能包含一个类或者接口。无论Java class...
  • javaclass文件的意义在哪里

    千次阅读 2017-07-10 09:17:54
    java的编译器在编译java类文件时,会将原有的文本文件(.java)翻译成二进制的字节码,并将这些字节码存储在.class文件。 也就是说java类文件中的属性、方法,以及类中的常量信息,都会被分别存储在.class文件中。...
  • Java 获取Class对象的三种方法

    千次阅读 2016-09-10 12:59:24
    Java中的java.lang.Class,简单理解就是为每个java对象的类型标识的类,虚拟机使用运行时类型信息选择正确的执行方法,用来保存这些运行时类型信息的就是Class类。虚拟机为每种类型管理一个独一无二的对象,即Class...
  • Java创建ClassTag的方法

    千次阅读 2017-10-25 10:56:23
    Java创建ClassTag的方法,我能找到的有三个方法。其中第三种方法,只要需要classtag的地方都可以直接用,参数都不需要。 1:ClassManifestFactory.classType( String.class )。 2:ClassTag$.MODULE$.apply( ...
  • 如何将javaclass文件反编译成java文件 jad:反编译工具下载 jad:反编译工具可以将class文件反编译成java文件假设将jad.exe安装在f:/java/jad目录下把要反编
  • java,class,dex转换过程

    万次阅读 2017-08-29 12:31:31
    class文件:.java文件经java编译器编译后生成对应的.java文件  生成方法1.在eclipse中选中某一个类,然后导出为jar文件。将得到的jar文件修改为.zip文件然后解压,即可看到想要的.class文件  生成方法2.使用cmd...
  • Java 查看class文件的汇编代码

    千次阅读 2016-08-26 13:44:19
    为了更好地理解Java代码,内部具体是怎么运行,我们常常会通过反汇编来查看汇编代码。Java本身也是提供这个支持的。 通过开启以下两个属性即可(关于具体参数配置,可以查看这里)java -XX...M3.javapublic class M3 {
  • windows下直接双击运行javaclass文件

    千次阅读 2018-04-01 16:18:44
    前两天刚学java,发现java源代码编译后的class文件不能直接在windows下双击运行,如下图中的Welcome.class如果想要运行只能在cmd或者powershell中输入:java Welcome 然后回车才能运行,很不方便。以下是解决办法:在...
  • 我第一次用java编写程序遇到了HelloJava.class拒绝访问的情况,我在网看了半天无果。来csdn求大牛给我来个详细解答,不胜感激
  • java.lang.ClassNotFoundException,原因是未加类包名所致,解决如下: String cName = .... Class c = Class.forName("所动态加载自定义的类所在的包报名." + cName); 则错误解决!!! ...
  • 首先对JAVA 名称官方参数进行说明。...通过以上官方java jvm参数命令,可知有两种设置classpath方式,这两种方式分别针对java class名、java -jar 两种启动方式。 方式一:java -classpath class名 -cp &...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,518,869
精华内容 2,607,547
关键字:

java怎么引用class

java 订阅