精华内容
下载资源
问答
  • Jmockdta是一款实现模拟JAVA类型或对象的实例化并随机初始化对象的数据的工具框架。单元测试的利器。
  • Java初始化对象工具 - 构造器

    千次阅读 多人点赞 2020-03-12 02:06:15
    本文关键字:对象、初始化、实例化、构造器、构造方法。明确了类与对象的关系后,我们知道:类只是一个定义的结构,用来表述我们想要描述的事物,即具备哪些属性(成员变量),可以产生哪些行为(方法)。那么具体...

    写在前面:博主是一只经过实战开发历练后投身培训事业的“小山猪”,昵称取自动画片《狮子王》中的“彭彭”,总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域,如今终有小成,愿将昔日所获与大家交流一二,希望对学习路上的你有所助益。同时,博主也想通过此次尝试打造一个完善的技术图书馆,任何与文章技术点有关的异常、错误、注意事项均会在末尾列出,欢迎大家通过各种方式提供素材。

    • 对于文章中出现的任何错误请大家批评指出,一定及时修改。
    • 有任何想要讨论和学习的问题可联系我:zhuyc@vip.163.com。
    • 发布文章的风格因专栏而异,均自成体系,不足之处请大家指正。

    Java初始化对象的工具 - 构造器

    本文关键字:对象、初始化、实例化、构造器、构造方法

    一、构造器的作用

    明确了类与对象的关系后,我们知道:类只是一个定义的结构,用来表述我们想要描述的事物,即具备哪些属性(成员变量),可以产生哪些行为(方法)。那么具体行为的发生,也就是方法的调用要靠对象来完成,同时属性值也要附着在对象上才有意义。创建对象的过程被叫做类的实例化,或者称为对象的初始化,在这个过程中需要使用的就是new关键字和类的构造器。
    对于相关概念还不清楚的同学请进传送门:Java中的基本操作单元 - 类和对象

    二、构造器的定义

    1. 构造器的别称

    没错,他们都是同一个意思。

    • 构造器
    • 构造方法
    • 构造函数

    2. 构造器定义格式

    构造器本身更像一种方法,因此定义的格式与方法类似,可以区别着进行记忆。构造器同样被定义在class的大括号内,构造器的定义格式如下:

    public class className{
        // 构造器定义开始
        [权限修饰符] 类名(参数列表){
            // 代码部分
        }
        // 构造器定义结束
    }
    

    从以上的结构我们看到,构造器的声明格式与方法类似:

    • 以权限修饰符开头
    • 不能被static、final、abstract等修饰符修饰
    • 无返回值类型
    • 方法名称与类名相同
    • 一个类中可以出现多个构造方法,区别在于参数列表不同

    那么,在这个构造方法当中我们都应该写些什么呢?还是从构造器的作用入手,既然他的作用是初始化一个对象,那么对象在初始化时最需要做的就是对属性赋值,所以如果有需要我们会在调用时传入某些属性的初始值,或者在对象初始化时执行某些代码,帮助我们判断对象初始化的状态。

    public class Student{
        public Student(){
            System.out.println("学生对象初始化成功");
            // 其他代码
        }
    }
    
    public class Test{
        public static void main(String[] args){
            Student student = new Student();
            // 执行效果 -> 输出:学生对象初始化成功
        }
    }
    

    对于创建对象时为属性赋值的用法将在构造器的重载中演示。

    3. 隐式构造器

    在刚刚开始学习面向对象部分时,可能都会存在一个疑问,之前定义的class都没有定义构造器呀,不是一样可以通过new来创建实例吗?这是因为当一个类被定义后,如果没有手动的创建任何的构造方法,会默认提供一个空的构造器,供初始化使用,这个过程是编译时完成的。

    public class Person{
    
    }
    

    我们对Person类进行编译,得到Person.class文件,然后我们对class文件进行反编译,就可以看到已经出现了一个空的构造器:

    Java程序在执行时,加载的都是.class文件,并且所生成的.class文件与我们定义的.java文件一般都是存在差异的。所以这就能够解释,为什么明明我们在.java文件中没有定义构造器,但是在创建对象时却可以使用new调用到。
    隐式构造器还有一个特点,就是如果我们已经手动创建了一个无参的构造器,或者一个有参的构造器,那么在编译时就不会生成无参构造器了。

    public class Person{
        public Person(String name){
            System.out.println(name);
        }
    }
    

    此时,由于我们已经手动指定了一个构造器了,所以在编译时就不会再产生默认的无参构造器了,只会有自己手动定义的构造器:

    那么,大家应该也注意到了一个问题,既然用new创建对象时是调用的构造器,那么现在我们自己定义了一个有参数的构造器,那么就会使得我们最常使用的new Person()这种实例化的代码报错,因为此时类中已经没有无参构造器可供调用了,也可以认为无参的构造器被覆盖了,必须要传入一个参数才能初始化对象。

    public class Test{
        public static void main(String[] args){
            Person person = new Person();
            // 编译不通过,已经无法调用无参构造器来初始化对象
        }
    }
    

    那么如果我们还是想用这个无参构造器来创建对象该怎么办呢?没错,手动声明一下就好了,里面不需要写任何内容:

    public class Person{
        // 无参构造器
        public Person(){}
        // 有参构造器,可以接收一个参数
        public Person(String name){
            System.out.println(name);
        }
    }
    

    我们来看一下效果,很明显,将会同时存在两个构造器,我们在使用new进行对象初始化的时候可以根据需要来使用。
    `

    public class Test{
        public static void main(String[] args){
            Person person1 = new Person();
            // 编译通过,执行后person1被成功实例化,无输出
            Person person2 = new Person("小明");
            // 编译通过,执行后person2被成功实例化,输出:小明
        }
    }
    

    4. 构造器的重载

    从上面的例子我们已经可以看到,一个类结构中可以存在多个构造器,用于在有不同需要时被调用。而且由于构造器本身的主要作用是用于为类的属性赋初始值,所以在构造器中我们会指定一些参数,用于被调用时传入,为当前类的属性赋值。

    public class Person{
        // 无参构造器
        public Person(){}
        // 两参构造器,可以给name和age属性赋值
        public Person(String name,int age){
            this.name = name;
            this.age = age;
        }
        // 三参构造器,可以给name、age和job属性赋值
        public Person(String name,int age,String job){
            this.name = name;
            this.age = age;
            this.job = job;
        }
        public String name;
        public int age;
        public String job;
    }
    

    在上面的代码中我们可以看到有三个构造器,名称相同,只有参数列表不同,这种关系被称为重载,在方法中也有类似的概念。可以看到构造器中存在部分代码,且都是赋值语句。

    • this关键字的用法

    this可以指代当前对象,使用this可以调用出直接在类下定义的成员(变量和方法),其中一个最主要的作用就是可以区分同名的变量。我们在进行变量命名时,一直强调见名知意,那么问题就来了:在类中定义的成员变量名称已经确定了,而构造器中传入的参数就是为了给这些属性赋值的,那么参数的名称是不是应该和类成员变量一样才更能表达意思呢?如果这样的话就造成了参数列表中的变量名称与类成员变量的名称同名,这时就可以通过this来区分。
    明确了this的用法,我们再来看构造器中的内容就很好理解了,将传入的参数赋值给当前对象的类成员变量,具体的调用过程我们看下面的例子。

    三、构造器的调用

    src
    └──edu
        └──sandtower
            └──bean
                │    Person.java
            └──test
                │    Test.java
    

    以上为实体类与测试类所在的目录结构,Person实体类所在包:edu.sandtower.bean,Test测试类所在包:edu.sandtower.test,则代码如下:

    package edu.sandtower.bean;
    
    public class Person{
        // 无参构造器
        public Person(){}
        // 三参构造器,可以给name、age和job属性赋值
        public Person(String name,int age,String job){
            this.name = name;
            this.age = age;
            this.job = job;
        }
        public String name;
        public int age;
        public String job;
    }
    
    package edu.sandtower.test;
    // 导包操作:指明需要使用的Person类的所在位置
    import edu.sandtower.bean.Person;
    
    public class Test{
        public static void main(String[] args){
            Person person1 = new Person();
            // person1被成功实例化,各属性无初始值,可以手动赋值
            person1.name = "小张";
            person1.age = 26;
            person1.job = "Linux运维工程师";
            Person person2 = new Person("小李",25,"Java开发工程师");
            // person2被成功实例化,并具有如下初始值
            // name:小李
            // age:25
            // job:Java开发工程师
            // 输出进行验证
            System.out.println("name:" + person2.name);
            System.out.println("age:" + person2.age);
            System.out.println("job:" + person2.job);
        }
    }
    

    在进行对象的初始化时,可以根据需要取得一个空的对象(如:person1)后手动赋值,也可以通过有参构造器直接对属性赋值(如:person2),避免逐一赋值的麻烦。

    在这里插入图片描述

    展开全文
  • 项目开发中,经常遇到需要给实例化对象设置属性值,并且当属性特别多时,setter属性占用很大篇幅,在此用反射实现实例化对象,并自动设置属性值。可以作为以后项目的小工具,方便开发。大致思路:(1)对需要实例化的...

    将之前学的Java知识进行汇总和整理,本篇主要讲述Java反射和使用用例。

    项目开发中,经常遇到需要给实例化对象设置属性值,并且当属性特别多时,setter属性占用很大篇幅,在此用反射实现实例化对象,并自动设置属性值。可以作为以后项目的小工具,方便开发。

    大致思路:(1)对需要实例化的Class对象,通过反射进行实例化;(2)将固定格式的参数注入到对象中。

    篇外话:该思路与Spring的IOC类似,(1)程序启动时,Spring会解析提前配置好的Bean信息(如通过XML配置或注解配置),将Bean抽象为BeanDefinition结构,其中包含类的全限定名和依赖的类信息,并注册到容器中(说白了就是key-value的map中)。(2)在程序第一次执行getBean()时,会注入依赖的对象,这个会设计级联注入,直到属性为基本类型。

    开始正文,下边代码是实现了类的实例化和属性设置功能,主要包括 简单数据类型设置 和 级联对象引用设置。

    (1)创建类实例化工厂类:包含实例化和设置属性值两个步骤;

    (2)StringUtils类用于处理setter和getter方法名

    (3)BeanUtils类用于设置属性,其中包含级联属性实例化

    具体过程已记录在代码注释中。

    importjava.lang.reflect.Field;importjava.lang.reflect.Method;importjava.text.SimpleDateFormat;importjava.util.Date;public classClassInstanceFactory{privateClassInstanceFactory(){}/*** 1.首先进行实例化;2.再对实例化对象设置属性值,格式“属性:值|属性:值”

    *@paramclazz Class反射实例化

    *@paramvalue 为实例化对象设置属性值

    *@param

    *@return

    */

    public static T createInstane(Classclazz, String value){try{

    Object obj= clazz.getDeclaredConstructor().newInstance();

    BeanUtils.setValue(obj, value);return(T)obj;

    }catch(Exception e){return null;

    }

    }

    }classStringUtils{/*** 首字母大写,以获取setter和getter方法

    *@paramstr

    *@return

    */

    public staticString initCap(String str){if(null == str || "".equals(str)){returnstr;

    }if(str.length() == 1){returnstr.toUpperCase();

    }else{return str.substring(0,1).toUpperCase()+str.substring(1);

    }

    }

    }//为实例化对象设置属性值

    classBeanUtils{public static voidsetValue(Object obj, String value){

    String[] attrs= value.split("\\|");for(int i = 0; i < attrs.length; i++){

    String[] attr= attrs[i].split("\\:");//判断是否是处理级联引用

    if(attr[0].contains(".")) {

    String[] str= attr[0].split("\\.");try{//1.获取级联属性是否为null

    Method getMethod = obj.getClass().getDeclaredMethod("get" + StringUtils.initCap(str[0]));

    Object tmp=getMethod.invoke(obj);if(tmp == null){//2.为null时,需要初始化后,再设置属性值//2.1 首先实例化

    Field field = obj.getClass().getDeclaredField(str[0]);

    tmp= field.getType().getDeclaredConstructor().newInstance();//2.2 设置级联引用的属性

    setValue(tmp, attrs[i].substring(attrs[i].indexOf(".")+1));//2.3 将实例化完成的级联属性设置到对象中

    Method method = obj.getClass().getDeclaredMethod("set" + StringUtils.initCap(str[0]), field.getType());

    method.invoke(obj, tmp);

    }else{//3.不为空时,直接设置级联引用的属性

    setValue(tmp, attrs[i].substring(attrs[i].indexOf(".")+1));

    }

    }catch(Exception e){

    }

    }else{//非级联引用

    try{//getField返回所有public的属性; getDeclaredField 返回类所有声明的属性

    Field field = obj.getClass().getDeclaredField(attr[0]);//getMethod 返回所有public的方法,包含父类 getDeclaredMethod返回所有声明的方法,不包含父类

    Method method = obj.getClass().getDeclaredMethod("set" + StringUtils.initCap(attr[0]), field.getType());//获取属性实际值

    Object val = convertType(field.getType().getName(), attr[1]);

    method.invoke(obj, val);

    }catch(Exception e) {

    }

    }

    }

    }private staticObject convertType(String type, String value){if(Integer.class.getName().equals(type) || "int".equals(type)) {returnInteger.valueOf(value);

    }else if(Double.class.getName().equals(type) || "double".equals(type)){returnDouble.valueOf(value);

    }else if(Long.class.getName().equals(type) || "long".equals(type)){returnLong.valueOf(value);

    }else if(Date.class.getName().equals(type)){

    SimpleDateFormat sdf= null;if(value.matches("\\d{4}-\\d{2}-\\d{2}")){

    sdf= new SimpleDateFormat("yyyy-MM-dd");

    }else if(value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {

    sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    }else{return newDate();

    }try{returnsdf.parse(value);

    }catch(Exception e){return newDate();

    }

    }else{returnvalue;

    }

    }

    }

    测试:

    /*** 对简单对象进行实例化,并给各属性赋值

    * 为避免大量setter代码出现,使用反射机制简化初始化过程*/

    public classReflectAndSimplObject {public static voidmain(String[] args){

    String value= "name:bob|age:80|birth:1990-10-10|dept.name:ssc|dept.company.name:td|dept.company1.name:ry";

    Person p= ClassInstanceFactory.createInstane(Person.class, value);

    System.out.println(p);

    }

    }classCompany{

    String name;publicString getName() {returnname;

    }public voidsetName(String name) {this.name =name;

    }

    @OverridepublicString toString() {return "Company{" +

    "name='" + name + '\'' +

    '}';

    }

    }classCompany1 {

    String name;publicString getName() {returnname;

    }public voidsetName(String name) {this.name =name;

    }

    @OverridepublicString toString() {return "Company1{" +

    "name='" + name + '\'' +

    '}';

    }

    }classDept{

    String name;longid;

    Company company;

    Company1 company1;publicString getName() {returnname;

    }public voidsetName(String name) {this.name =name;

    }publicCompany getCompany() {returncompany;

    }public voidsetCompany(Company company) {this.company =company;

    }public longgetId() {returnid;

    }public void setId(longid) {this.id =id;

    }publicCompany1 getCompany1() {returncompany1;

    }public voidsetCompany1(Company1 company1) {this.company1 =company1;

    }

    @OverridepublicString toString() {return "Dept{" +

    "name='" + name + '\'' +

    ", id=" + id +

    ", company=" + company +

    ", company1=" + company1 +

    '}';

    }

    }classPerson{

    String name;intage;

    Date birth;

    Dept dept;publicString getName() {returnname;

    }public voidsetName(String name) {this.name =name;

    }public intgetAge() {returnage;

    }public void setAge(intage) {this.age =age;

    }publicDate getBirth() {returnbirth;

    }public voidsetBirth(Date birth) {this.birth =birth;

    }publicDept getDept() {returndept;

    }public voidsetDept(Dept dept) {this.dept =dept;

    }

    @OverridepublicString toString() {return "Person{" +

    "name='" + name + '\'' +

    ", age=" + age +

    ", birth=" + birth +

    ", dept=" + dept +

    '}';

    }

    }

    输出:

    Person{name='bob', age=80, birth=Wed Oct 10 00:00:00 CST 1990, dept=Dept{name='ssc', id=0, company=Company{name='td'}, company1=Company1{name='ry'}}}

    总结

    反射的使用,将增加代码的灵活性,并使代码编写更简洁。可以将这个作为以后项目的工具,简化diamagnetic编写。

    展开全文
  • java对象实例化问题

    2019-09-06 16:12:40
    最终发现是参考的示例代码中流对象实例化写法有问题。 错误写法: try { ImageIO.write(bufferImage, imageType, new FileOutputStream(outFilePath) ); fileOutputStream.close(); } ca...

    在调用绘图工具类的时候,发现绘图之后生成的图片一直被占用,流无法释放。
    最终发现是参考的示例代码中流对象的实例化写法有问题。

    错误写法:

    try {
            ImageIO.write(bufferImage, imageType, new FileOutputStream(outFilePath) );
            fileOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    

    图中的 FileOutputStream是在方法内部new的。

    问题:这种写法,在方法执行结束以后,new的对象会被释放,但是对象占用的流并不会一起释放,导致流占用问题。

    正确写法:

    try {
        FileOutputStream fileOutputStream = new FileOutputStream(outFilePath);
        ImageIO.write(bufferImage, imageType, fileOutputStream);
        fileOutputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    显式声明和实例化流对象,再显式关闭

    展开全文
  • 如果Java对象拥有不带参数的构造函数,那么可以在JavaFX代码里直接实例化: var var1 = ArrayList{}; 如果目标Java类只有带参数的构造函数就有些麻烦,需要分2步进行,首先新建一个Java工具JavaUtils.java,...

    如果Java类对象拥有不带参数的构造函数,那么可以在JavaFX代码里直接实例化:

    var var1 = ArrayList{};

    如果目标Java类只有带参数的构造函数就有些麻烦,需要分2步进行,首先新建一个Java工具类JavaUtils.java,在这个类里将你目标类实例化完成后通过赋值语句将其赋值给JavaFX变量:

    1、编写JavaUtils.java

    import java.net.MalformedURLException; import java.net.URL; /** * * @author Leon Chen */ public class JavaUtils { public static URL getURL(String spec) throws MalformedURLException{ return new URL(spec); } }

    2、在JavaFX代码里使用JavaUtils生成URL类实例

    var url = JavaUtils.getURL(“http://www.jqueen.org”);

    目前JavaFX版本为1.2,在Java和JavaFX代码的相互调用上还有很多不方便的地方,希望以后的版本会有改进。

    展开全文
  • Java基础之面向对象  面向对象编程OOP(Object Oriented Programming)  我个人理解的面向对象的思想是:在完成一件事情的过程中,更多的注意力放在完成个事情的时候使用这个工具上,而不是把重点放在过程中。 ...
  • java 工具类是可以实例化的,只是完全没有必要罢了,因为工具类实际上提供的是在一些业务中通用的方法调用,将其做成静态的非常合适,无需实例化,若实例化就需要一定内存空间,工具类直接提供静态方法就可以避免 ...
  • 定义一个交通工具(Vehicle)的类其中有: 属性:...最后在测试类Vehicle中的main()中实例化一个交通工具对象并通过方法给它初始化speed,size的值并且打印出来。另外调用加速减速的方法对速度进行改变。 代码如下: ...
  • 工具类是需要被反复使用的,而工具类的内容又是相同的,如果每个调用者都实例化工具类就会在内存中存储大量重复数据。 工具类成为共有部分–>静态(在工具类a里定义一个静态的工具类a的实例b,因为实例b是静态的...
  • 让一个类不能被实例化的方法什么样的场景会需要让一个类不能被实例化工具类(utility class),实例化对它们没有意义的工具类。这时候,就要做到不让该类被实例化java.lang.Math:把与Math相关的基本类型的值和相关的...
  • JVisualVM 简介案例分析准备模拟内存泄漏样例使用JVisualVM分析内存泄漏JVisualVM 远程监控 TomcatJVisualVM 简介VisualVM 是...象,已被GC的对象,反向查看分配的堆栈(如100个String对象分别由哪几个对象分配...
  • JVisualVM 简介VisualVM 是Netbeans的profile子项目,已在JDK6.0 update 7 中自带,能够监控线程,内存情况,查看方法的CPU时间和内存中的对 象,已被GC的对象,反向查看分配的堆栈(如100个String对象分别由哪几个...
  • JVisualVM 简介案例分析准备模拟内存泄漏样例使用JVisualVM分析内存泄漏JVisualVM 远程监控 TomcatJVisualVM 简介VisualVM 是Netbeans的...象,已被GC的对象,反向查看分配的堆栈(如100个String对象分别由哪几...
  • java 对象克隆工具

    千次阅读 2017-09-04 10:18:18
    java 对象克隆将序列对象进行克隆代码实例
  • 读书笔记 仅供参考不可实例化类不希望被实例化,例如工具类,包含的都是静态方法和静态属性,实例对它没有任何意义。错误的做法将类做成抽象类。 原因:抽象类可以被继承,子类可以被实例化。正确的做法包含一个...
  • 我们在写代码过程中,常常会定义一些工具类,这些类的所有方法都是静态的,所以这些类的实例化是没有必要的,那么如何保证这些类不被实例化呢 方法1:将该类定义成抽象类 这种方式虽然能避免该类不能被创建实例,...
  • 实例化对象的方法

    千次阅读 2007-06-20 10:23:00
    Class.forName(str).newInstance();例子:1、 为某研究所编写一个通用程序,用来计算每一种交通工具运行1000公里所需的时间,已知每种交通工具的参数都是3个整数A、B、C的表达式...需要编写三类:ComputeTime.java,P
  • 作者:徐轻尘原文:https://www.cnblogs.com/xifengxiaoma/p/9402497.htmlJVisualVM 简介VisualVM 是 Netbeans 的 profile 子项目,已在 JDK6.0 update 7...象,已被 GC 的对象,反向查看分配的堆栈(如 100 个 Strin...
  • 练习题】类的成员变量:请定义一个交通工具(V ehicle)的类,其中有:属性:速度...最后在测试类V ehicle中的main()中实例化一个交通工具对象,并通过方法给它初始化speed,size的值,并且通过打印出来。另外,调用...
  • JVisualVM 简介VisualVM 是Netbeans的profile子项目,已在JDK6.0 update 7 中自带,能够监控线程,内存情况,查看方法的CPU时间和内存中的对 象,已被GC的对象,反向查看分配的堆栈(如100个String对象分别由哪几个...
  • 作者:朝雨忆轻尘来源:https://urlify.cn/FJ7NF3# JVisualVM 简介VisualVM 是Netbeans的profile子项目,已在JDK6.0 update 7 中自带,能够监控线程,内存情况,查看方法的CPU时间和内存中的对 象,已被GC的对象,...
  • 这样的工具类不希望被实例化,因为没有任何意义,但是在缺少显式构造器的情况下,编译器会自动提供一个公有的,无参的隐式构造器。 企图将类定义为抽象类来强制该类不可被实例化也是行不通的,该类还是可以被
  • 1、给不可实例化的类提供私有构造器比如:每个项目中都有很多工具类,提供了很多static类型的方法供大家使用,谁也不希望看到下面的代码:TextUtils textUtils = new TextUtils();if(textUtils.isDigitsOnly("123"))...
  • 1.很多工具类不希望被实例化,实例对他没有任何意义。在缺少显式构造器的情况下,编译器会自动提供一个公有的,无参的缺省构造器(default constructor). 2.企图通过将类做成抽象类来强制该类不可被实例化,这是行...

空空如也

空空如也

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

java实例化对象工具

java 订阅