zoukankan      html  css  js  c++  java
  • java面试(反射)05

    1.什么是反射

    JAVA反射机制是在运行状态中,对于任意一个类,都能够获取这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取类信息以及动态调用对象内容就称为java语言的反射机制

    2.反射的作用

    • 在运行时判断任意一个对象所属的类;

    • 在运行时构造任意一个类的对象;

    • 在运行时判断任意一个类所具有的成员变量和方法;

    • 在运行时调用任意一个对象的方法;

    3.反射的实现

     我们知道,要使用一个类,就要先把它加载到虚拟机中,生成一个Class对象。这个class对象就保存了这个类的一切信息。

        反射机制的实现,就是获取这个Class对象,通过Class对象去访问类、对象的元数据以及运行时的数据。

        有三种方法获得类的Class对象:Class.forName(String className)、className.class、实例对象.getClass();

    4.什么是 Java 序列化?什么情况下需要序列化?

    Java 序列化是为了保存各种对象在内存中的状态,并且可以把保存的对象状态再读出来。

    以下情况需要使用 Java 序列化:

    • 想把的内存中的对象状态保存到一个文件中或者数据库中时候;
    • 想用套接字在网络上传送对象的时候;
    • 想通过RMI(远程方法调用)传输对象的时候。

    5.动态代理是什么?有哪些应用?

    动态代理是运行时动态生成代理类。

    动态代理的应用有 spring aop、hibernate 数据查询、测试框架的后端 mock、rpc,Java注解对象获取等。

    6.怎么实现动态代理?

    JDK 原生动态代理和 cglib 动态代理。JDK 原生动态代理是基于接口实现的,而 cglib 是基于继承当前类的子类实现的。

    7.为什么要使用克隆对象?

    在java中,我们使用对象的时候直接去new一个对象就好了,为什么还要克隆对象呢?

           当我们new一个对象之后是要对该对象进行初始化的,不然这个对象是空的没有内容。而使用克隆,则会得到一个原对象以及原对象里面包含的内容。例如,你有一个User对象,里面的包含了相关的属性。此时你想要修改里面的某一属性,但又不想破坏原对象里面的数据,此时就可以克隆User这个对象,然后在克隆的这个User对象上进行修改操作。除此,如果你在操作完之后判断一下属性是否更改成功,则使用克隆的对象和原对象做一下对比即可。

    8.如何克隆一个对象?

    8.1浅复制

    浅克隆就是把原对象中的一些属性值克隆过来。使用clone()方法进行浅克隆。但注意:必须要在被克隆类上实现Cloneable接口,并重写clone方法。若不没有实现该接口,则会抛出CloneNotSupportedException异常!

    package interview;
    
    public class CloneTest {
    
        public static void main(String[] args) throws CloneNotSupportedException {
            // TODO Auto-generated method stub
            User user = new User();
            user.setName("张三");
            user.setAge(18);
            System.out.println("原对象(user)的属性值:");
            System.out.println("姓名为:" + user.getName() + ",年龄为:" + user.getAge()+"
    ");
    
            // 对user对象进行克隆
            User user1 = (User) user.clone();
            // 查看一下克隆对象中的属性值
            System.out.println("克隆后user1对象中的属性值:");
            System.out.println("姓名为:" + user1.getName() + ",年龄为:" + user1.getAge()+"
    "); // 结果和原对象中属性值相同
    
            // 对user1对象进行修改
            user1.setName("李四");
            // 查看修改后的结果
            System.out.println("user1对象进行修改后的属性值:");
            System.out.println("姓名为:" + user1.getName() + ",年龄为:" + user1.getAge()+"
    "); 
            
            System.out.println("user1对象进行修改后user对象的属性值:");
            System.out.println("姓名为:" + user.getName() + ",年龄为:" + user.getAge()+"
    "); 
        }
    
    }
    
    class User implements Cloneable {
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            // TODO Auto-generated method stub
            return super.clone();
        }
    }

    从结果上可以看出,克隆对象user1和原对象user在修改属性数据时,两个对象之间的数据互不受影响。

           那么如果后期需要调整代码,需要在原有的user对象中添加一个引用类型Address字段,那么克隆的user1对象会能受到影响吗?能和原对象user中的数据一致吗?

    看下面代码演示,在原有基础代码上加入一个Address的类,并分别在User类和Address类中加入重写Object的方法。注意:User类中的引用address字段的权限修饰符为public,否则无法运行!

    package interview;
    
    public class CloneTest {
    
        public static void main(String[] args) throws CloneNotSupportedException {
            // TODO Auto-generated method stub
            // 创建原对象,并为原对象中的属性进行赋值,然后打印出结果
            Address address = new Address("中国", "山东");
            User user = new User("张三", 18, address);
            System.out.println("原对象(user)的属性值:");
            System.out.println("姓名为:" + user.getName() + ",年龄为:" + user.getAge() + ",地址为:" + user.getAddress() + "
    ");
    
            // 对user对象进行克隆
            User user1 = (User) user.clone();
            // 查看一下克隆对象中的属性值
            System.out.println("克隆后user1对象中的属性值:");
            System.out.println("姓名为:" + user1.getName() + ",年龄为:" + user1.getAge() + ",地址为:" + user1.getAddress() + "
    ");
            
             // 对user1对象进行修改
             user1.setName("李四");
             user1.getAddress().setCity("北京");
             // 查看修改后的结果
             System.out.println("user1对象进行修改后的属性值:");
             System.out.println("姓名为:" + user1.getName() + ",年龄为:" + user1.getAge() +",地址为:" + user1.getAddress() + "
    ");
            
             System.out.println("user1对象进行修改后user对象的属性值:");
             System.out.println("姓名为:" + user.getName() + ",年龄为:" + user.getAge() + ",地址为:" + user.getAddress() + "
    ");
        }
    
    }
    
    class User implements Cloneable {
        private String name;
        private int age;
        private Address address;
    
        public User(String name, int age, Address address) {
            this.name = name;
            this.age = age;
            this.address = address;
        }
    
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            // TODO Auto-generated method stub
            return super.clone();
        }
    }
    
    // 定义一个address类
    class Address {
        private String country;
        private String city;
    
        public Address(String country, String city) {
            this.country = country;
            this.city = city;
        }
    
        public String getCountry() {
            return country;
        }
    
        public void setCountry(String country) {
            this.country = country;
        }
    
        public String getCity() {
            return city;
        }
    
        public void setCity(String city) {
            this.city = city;
        }
    
        @Override
        public String toString() {
            return "Address [country=" + country + ", city=" + city + "]";
        }
    
    }

    从结果上看,user1在克隆完后修改了姓名和地址值,修改后和原对象对比,发现姓名和地址的确发生了改变。但再次查看原对象的结果时,发现原对象的姓名值虽没变,但地址值却随着user1对象的改变而改变了!这样的话反而失去了克隆的意义。那么为什么会出现这种情况呢?因为浅克隆只是克隆原对象中的引用类型指向,并非克隆了原对象中的全部数据。

    3.2 深克隆

    深克隆和浅克隆的区别在于:浅克隆只克隆了原对象的引用类型的指向。深克隆则是克隆了原对象的所有。也就是说像上面案例所示,如果使两个对象之间互不影响,则使用深克隆。

    深克隆的使用:在引用类型所在的类使其实现Cloneable接口,并使用public修饰符重写Clone()方法。

    package interview;
    
    public class CloneTest {
    
        public static void main(String[] args) throws CloneNotSupportedException {
            // TODO Auto-generated method stub
            // 创建原对象,并为原对象中的属性进行赋值,然后打印出结果
            Address address = new Address("中国", "山东");
            User user = new User("张三", 18, address);
            System.out.println("原对象(user)的属性值:");
            System.out.println("姓名为:" + user.getName() + ",年龄为:" + user.getAge() + ",地址为:" + user.getAddress() + "
    ");
    
            // 对user对象进行克隆
            User user1 = (User) user.clone();
            // 查看一下克隆对象中的属性值
            System.out.println("克隆后user1对象中的属性值:");
            System.out.println("姓名为:" + user1.getName() + ",年龄为:" + user1.getAge() + ",地址为:" + user1.getAddress() + "
    ");
    
            // 对user1对象进行修改
            user1.setName("李四");
            user1.getAddress().setCity("北京");
            // 查看修改后的结果
            System.out.println("user1对象进行修改后的属性值:");
            System.out.println("姓名为:" + user1.getName() + ",年龄为:" + user1.getAge() + ",地址为:" + user1.getAddress() + "
    ");
    
            System.out.println("user1对象进行修改后user对象的属性值:");
            System.out.println("姓名为:" + user.getName() + ",年龄为:" + user.getAge() + ",地址为:" + user.getAddress() + "
    ");
        }
    
    }
    
    class User implements Cloneable {
        private String name;
        private int age;
        private Address address;
    
        public User(String name, int age, Address address) {
            this.name = name;
            this.age = age;
            this.address = address;
        }
    
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            // TODO Auto-generated method stub
            // 这一步返回的这个user对象还只是一个浅克隆,
            User user = (User) super.clone();
            // 然后克隆的过程中获得这个克隆的user,然后调用这个getAddress()这个方方法得到这个Addrress对象。然后实现克隆。在设置到这个user中的Address。
            // 这样实现了双层克隆使得那个Address对象也得到了复制。
            user.setAddress((Address) user.getAddress().clone());
            return user;
        }
    }
    
    // 定义一个address类
    class Address implements Cloneable {
        private String country;
        private String city;
    
        public Address(String country, String city) {
            this.country = country;
            this.city = city;
        }
    
        public String getCountry() {
            return country;
        }
    
        public void setCountry(String country) {
            this.country = country;
        }
    
        public String getCity() {
            return city;
        }
    
        public void setCity(String city) {
            this.city = city;
        }
    
        @Override
        public String toString() {
            return "Address [country=" + country + ", city=" + city + "]";
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            // TODO Auto-generated method stub
            return super.clone();
        }
    
    }

    9.如何实现对象克隆?

    • 实现 Cloneable 接口并重写 Object 类中的 clone() 方法。
    • 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。
  • 相关阅读:
    HBase with MapReduce (MultiTable Read)
    HBase with MapReduce (SummaryToFile)
    HBase with MapReduce (Summary)
    HBase with MapReduce (Read and Write)
    HBase with MapReduce (Only Read)
    Hbase中的BloomFilter(布隆过滤器)
    HBase的快照技术
    How To Use Hbase Bulk Loading
    Cloudera-Manager修改集群的IP
    Java中的HashSet和TreeSet
  • 原文地址:https://www.cnblogs.com/xinmomoyan/p/11468267.html
Copyright © 2011-2022 走看看