Java创建对象小结 叁歲伎倆 2022-03-09 04:58 155阅读 0赞 Java SE中必可避免的会学到new关键字(用以创建对象),之后又了解到了克隆以及反射都可以创建对象。。今天又学到了静态工厂以及构建器,所以呢,在此做一个小结。 > 下面我先以创建对象的几种方式开始讲起,然后在优化构造器用以创建对象(即为何尽量使用构建器而不是其他的几种),介绍的不周到的地方还请大佬见谅,我还是个弟弟~~~~ ### 创建对象五种方式 ### * ### new关键字 ### 语法:类名 对象名=new 类名(); > Student student1=new Student("小刘",22); * ### 反射:Class类的newInstance方法 ### 语法:java.lang.Class Class 类对象名称=java.lang.Class.forName(要实例化的类全称);类名 对象名=(类名)Class类对象 名称.newInstance(); > Class cl=Class.forName("Student"); > > Student student2=(Student)cl.newInstance(); * ### 反射:Constructor类的newInstance方法 ### > Constructor<Student> constructor = Student.class.getInstance() > Student stu3 = constructor.newInstance(); 注意:对于构造器的反射还可以解析私有构造器,反射还可以解析一个类的方法还有属性,详情看我另外一篇博客或者百度。。 > Class classPer1=Class.forName("demo.Person"); > //int为Person类私有构造器中的参数,如果为多参则依次添加多个参数的类即可 > Constructor constructor=classPer1.getDeclaredConstructor(int.class); > //暴力反射 > constructor.setAccessible(true); > Person person=(Person) constructor.newInstance(2); * ### 克隆:object.clone() (不常用) ### 语法:类名对象名=(类名)已创建好的类对象名.clone(); > Student student3=(Student)student2.clone(); * ### 对象的反序列化 ### > ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj")); 对上述示例的说明如下: * new 关键字:调用类的无参构造方法,也是java中高耦合的罪魁祸首。 * Class 对象的 newInstance():调用类的无参构造方法。Class的newInstance方法内部是调用Constructor的newInstance()方法。其实这也是众多框架Spring、Hibernate、Struts等使用后者的方式。 * Constructor类的 newInstance():调用类的无参认构造方法,或者有参构造。 * Object 类的 clone() :必须实现 Cloneable 接口。不会调用类的构造方法,它会创建一个复制的对象,这个对象和原来的对象具有不同的内存地址,但它们的属性值相同。 * 对象的反序列化:不会调用类的构造方法 ### 优化过程 ### * ### 构造器 ### 问题:参照静态工厂的优点就是它的问题。。 * ### 静态工厂 ### 优点: 有名称,便于阅读。 Singleton 可以返回任意子类型的对象,提高了灵活性。 创建参数化实例的时候,它使得代码变得简单。 缺点:不能很好地扩展到大量的可选参数,即对类中大量的属性实例化不能很好地解决。 模板: package serviceprovider; public class Car { private int price; private int length; private int height; private int width; private String color; private static final Car redCar = new Car("red"); private static final Car blueCar = new Car("blue"); private static final Car bestSaleCar = new Car(350000, 3, 2, 2, "blue"); public Car(int price) { super(); this.price = price; } public Car(int price, int length, int height, int width, String color) { super(); this.price = price; this.length = length; this.height = height; this.width = width; this.color = color; } public Car(String color) { super(); this.color = color; } /** * 下面是静态工厂方法 */ public static Car getRedCar(){ return redCar; } public static Car getBlueCar(){ return blueCar; } /** * 获取这个季度卖的最好的车 * @return */ public static Car getBestSaleCar(){ return bestSaleCar; } } * ### 重叠构造器,即第一个构造方法只提供必要参数,第二个构造器有一个可选参数,第三个构造器有两个可选参数。。直到最后一个构造以包含了所有的可选参数 ### 优点:可行 缺点:当有许多参数的时候,客户代码很难编写,并且任然难以阅读。 * ### Javabean方式,即setter和getter方法 ### 优点:与重叠构造器类似,可行。 缺点:Javabean模式自身有着很严重的缺点,构造过程被分到了几个调用中,在构造过程中可能处于不一致的状态,并且还需 要程序员付出额外的努力来确保它的线程安全。 * ### 构建器 ### 优点:保证像重叠构造器那样的安全性,也能保证像Javabean模式那么好的可读性。 缺点:可能就是在创建对象之前,必须先创建它的构建器。。 示例: public class NutritionFcts{ private final int servingSize; private final int servings; private final int calories; private final int fat; private final int sodium; private final int carbohydrate; public static class Builder{ //Required parameters private int servingSize; private int servings; //Optional parameters---initalized to default values private int calories=0; private int fat=0; private int carbohydrate=0; private int sodium=0; public Builder(int servingSize,int servings){ this.servings=servings; this.servingSize=servingSize; } public Builder calories(int val){ calories=val; return this; } public Builder fat(int val){ fat=val; return this; } public Builder carbohydrate(int val){ carbohydrate=val; return this; } public Builder sodium(int val){ sodium=val; return this; } public NutritionFcts builder(){ return new NutritionFcts(); } } private NutritionFcts(Builder builder){ servingSize=builder.servingSize; servings=builder.servings; calories=builder.calories; fat=builder.fat; carbohydrate=builder.carbohydrate; sodium=builder.sodium; } } //客户端代码 NutritionFcts cocaCola=new NutritionFcts.Builder(200,20).calories(100).fat(20).carbohydrate(65).sodium(89).builder(); ### 通用生成对象Generator(可做工具类) ### 1、申明一个Generator接口,提供一个next()方法,用以返回一个新的类对象。 > public interface Generator<T> \{ > T next(); > \} 2、定义一个BasicGenerator类,对Generator接口进行实现,用以生成某个类的对象。通过create()方法创建新的对象,使用泛型参数。 > package generator; > > > /\*\* > \* @author wangjie > \* @version 2018/11/19 > \* 一个通用的generator > \*/ > public class BasicGenerator<T> implements Generator<T> \{ > private Class<T> type; > public BasicGenerator(Class<T> type)\{ > this.type = type; > \} > @Override > public T next()\{ > try\{ > return type.newInstance(); > \}catch(Exception e)\{ > throw new RuntimeException(e); > \} > \} > > public static <T> Generator<T> create(Class<T> type)\{ > return new BasicGenerator<T>(type); > \} > > \} 3、定义一个具有默认构造器的简单类:这个类CountedObject能够实现计数功能,告诉我们创建了几个CountedObject实例,并通过toString()方法打印其编号。 > package generator; > > /\*\* > \* @author wangjie > \* @version 2018/11/19 > \*/ > public class CountedObject \{ > private static long counter = 0; > private final long id = counter++; > public long id()\{ return id; \} > public String toString()\{ return "CountedObject " + id; \} > \} 4、此时,可以使用BasicGenerator很容易地为CountedObject类创建一个Generator: > package generator; > > /\*\* > \* @author wangjie > \* @version 2018/11/19 > \*/ > public class BasicGeneratorDemo \{ > public static void main(String\[\] args) \{ > Generator<CountedObject> gen = BasicGenerator.create(CountedObject.class); > for (int i = 0; i < 5; i++) \{ > System.out.println(gen.next()); > \} > \} > \}
还没有评论,来说两句吧...