如何创建POJO?

70

最近我听说过“POJOs”(普通旧Java对象)。我谷歌了一下,但仍然不太理解这个概念。有人能给我一个清晰的POJO描述吗?

考虑一个类"Person",包含变量"id,name,address,salary"——我如何为这种情况创建一个POJO?下面的代码是POJO吗?

public class Person {
    //variables
    People people = new People();
    private int id;
    private String name;
    private String address;
    private int salary;


    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getAddress() {
        return address;
    }

    public int getSalary() {
        return salary;
    }

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

    public void setName() {
        this.name = name;
    }

    public void setAddress() {
        this.address = address;
    }

    public void setSalary() {
        this.salary = salary;
    }
}

1
请查看我对类似问题的答案:https://dev59.com/YHA75IYBdhLWcg3wRWoU#3392625。这是指POCO的.NET版本,但基本原理相同。 - RPM1984
@Tamil,你能再跟我解释一遍吗?关于POJO。 - Poovizhirajan N
@Poovizhirajan.N,抱歉回复晚了。不知怎么错过了。 - user405398
11个回答

83
一个POJO只是一个去除了限制的普通旧Java Bean。Java Bean必须满足以下要求:
  1. 默认无参构造函数
  2. 遵循Bean约定:对于名为foo的可变属性,getFoo(或对于布尔值,isFoo)和setFoo方法;如果foo不可变,则去掉setFoo。
  3. 必须实现java.io.Serializable接口
POJO不强制执行这些要求。它只是字面意思:在JDK下编译的对象可以被视为纯粹的旧Java对象。不需要应用服务器、基类或接口即可使用。
POJO这个首字母缩写是针对EJB 2.0提出的,该版本要求多个接口、扩展基类以及许多方法才能完成简单的事情。一些人反抗了这种复杂性,罗德·约翰逊(Rod Johnson)和马丁·福勒(Martin Fowler)等人试图找到一种实现企业规模解决方案的方法,而不必编写EJB。
马丁·福勒创造了一个新的缩写。
罗德·约翰逊写了《没有EJB的J2EE》,编写了Spring,影响了EJB,以至于版本3.1看起来非常像Spring和Hibernate,并从VMWare获得了甜美的IPO。
这里有一个可以理解的例子:
public class MyFirstPojo
{
    private String name;

    public static void main(String [] args)
    {
       for (String arg : args)
       {
          MyFirstPojo pojo = new MyFirstPojo(arg);  // Here's how you create a POJO
          System.out.println(pojo); 
       }
    }

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

    public String getName() { return this.name; } 

    public String toString() { return this.name; } 
}

16
有些人可以比阅读更快地理解实际演示,我就是其中之一。 - user405398
你的特定示例是不可变的,但其他示例是可变的。你只是碰巧让你的示例不可变吗?POJO中包含对可变对象的非共享引用以封装其状态的目的和包含标识可变对象的引用(其他引用也存在)以封装其身份的目的之间有区别吗? - supercat
@duffymo 抱歉如果我错了,这是否违反了无参数规则/指令? - diyoda_
7
我认为我在回答中已经说得很清楚了:要求无参构造函数是Java Bean的要求,但对于POJO来说并非如此。此外,任何规则都可以被打破。了解规则,知道例外,并理解后果。这是软件开发,不是谋杀案庭审。 - duffymo
1
请再次阅读。Java Bean标准要求实现Serializable接口;而POJO则不需要。 - duffymo
显示剩余6条评论

29

POJO:- POJO是一个Java对象,除了Java语言规范强制执行的限制之外没有任何限制。

POJO的属性:

  1. 所有属性必须是公共的setter和getter方法
  2. 所有实例变量应该是私有的
  3. 不应扩展预定义的类。
  4. 不应实现预定的接口。
  5. 不应包含预定的注释。
  6. 它可能没有任何参数构造函数。

POJO的示例:

public class POJO {

    private String value;

    public String getValue() {
         return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

#1,#2与维基百科上的定义相矛盾。https://en.wikipedia.org/wiki/Plain_Old_Java_Object#Definition。您正在描述“JavaBean POJO”(这个术语我认为是自相矛盾的,但这只是我的看法)。 - Nilzor
术语“property”是否合适?也许你的意思是“method”? - Valerio Bozz

5

一个POJO是一个简单的Java对象

来自我链接到的维基百科文章:

在计算机软件中,POJO是Plain Old Java Object的首字母缩写。这个名称强调了给定对象是一个普通的Java对象,不是一个特殊的对象,特别是不是一个企业级JavaBean

你的类似乎已经是一个POJO。


4

POJO类充当了一个bean,用于设置和获取值。

public class Data
{


private int id;
    private String deptname;
    private String date;
    private String name;
    private String mdate;
    private String mname;

    public int getId() {
        return id;
    }

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

    public String getDeptname() {
        return deptname;
    }

    public void setDeptname(String deptname) {
        this.deptname = deptname;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMdate() {
        return mdate;
    }

    public void setMdate(String mdate) {
        this.mdate = mdate;
    }

    public String getMname() {
        return mname;
    }

    public void setMname(String mname) {
        this.mname = mname;
    }
}

2
根据Martin Fowler的说法,
引用:
“该术语是在Rebecca Parsons,Josh MacKenzie和我准备在2000年9月举行的一次会议上发言时创造的。在演讲中,我们指出了将业务逻辑编码到常规java对象中而不是使用实体bean的许多好处。我们想知道为什么人们如此反对在其系统中使用常规对象,并得出结论是因为简单的对象缺乏一个花哨的名称。所以我们给了它们一个名字,它非常受欢迎。”
通常,POJO不受任何限制,任何Java对象都可以称为POJO,但有一些方向。定义良好的POJO应遵循以下方向。
  1. POJO中的每个变量都应声明为private。
  2. 默认构造函数应覆盖为public可访问性。
  3. 每个变量应具有其Setter-Getter方法,具有public可访问性。
  4. 通常,POJO应重写Object的equals(),hashCode()和toString()方法(但这并非强制要求)。
  5. 覆盖Comparable接口的compare()方法用于排序(最好但不是强制性的)。
根据Java语言规范,POJO不应该具有以下功能:
  1. 扩展预定义类
  2. 实现预定义接口
  3. 包含预定义注释

然而,开发人员和框架仍需要使用预定义的注释来实现诸如持久性、声明式事务管理等功能,以描述一个POJO。因此,如果对象在添加任何注释之前是POJO,则在删除注释后将返回到POJO状态,那么它仍然可以被认为是POJO。

JavaBean是一种特殊类型的POJO,它是可序列化的,具有无参构造函数,并且允许使用遵循简单命名约定的getter和setter方法访问属性。

了解更多关于Plain Old Java Object (POJO) Explained的信息。


但是每个Java类至少都继承了Object类,而Object类并没有继承其他任何类?我们应该添加“不能继承除Object以外的其他类”还是“不能显式地继承任何类”? - Badri Paudel
实际上这些不是硬性规定,而且我们也不需要扩展Object,因为它已经默认完成了。 - Naresh Joshi

2
当您没有采取任何措施特别设计用于特定框架、ORM或其他需要特殊类的系统时,您拥有一个普通的Java对象,即POJO。
具有讽刺意味的是,创造这个术语的原因之一是人们在明智情况下避免使用它们,并且有些人得出结论认为这是因为它们没有花哨的名称。具有讽刺意味的是,因为您的问题证明了这种方法的有效性。
将旧的POD“Plain Old Data”与C ++类进行比较,它不会执行C结构无法执行的任何操作(或多或少,非虚成员不是析构函数或微不足道的构造函数并不会使其被视为POD),以及.NET中更新且更直接可比的POCO“Plain Old CLR Object”。

谢谢您的回复,前辈。但我想要一些实际的解释。 - user405398
你想要一个“非特殊”的命名法的实际解释吗?真的吗? - Jon Hanna

1

主要有三种选项用于映射目的:

  1. 序列化
  2. XML 映射
  3. POJO 映射 (Plain Old Java Objects)

在使用 POJO 类时,开发人员可以轻松地将其与数据库进行映射。POJO 类是为数据库创建的,同时还会创建值对象类,并具有 getter 和 setter 方法,这些方法可以轻松地保存内容。

因此,为了在 Java 与数据库之间进行映射,实现了值对象和 POJO 类。


1
import java.io.Serializable;

public class Course implements Serializable {

    protected int courseId;
    protected String courseName;
    protected String courseType;

    public Course() {
        courseName = new String();
        courseType = new String();
    }

    public Course(String courseName, String courseType) {
        this.courseName = courseName;
        this.courseType = courseType;
    }

    public Course(int courseId, String courseName, String courseType) {
        this.courseId = courseId;
        this.courseName = courseName;
        this.courseType = courseType;
    }

    public int getCourseId() {
        return courseId;
    }

    public void setCourseId(int courseId) {
        this.courseId = courseId;
    }

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public String getCourseType() {
        return courseType;
    }

    public void setCourseType(String courseType) {
        this.courseType = courseType;
    }

    @Override
    public int hashCode() {
        return courseId;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj != null || obj instanceof Course) {
            Course c = (Course) obj;
            if (courseId == c.courseId && courseName.equals(c.courseName)
                    && courseType.equals(c.courseType))
                return true;
        }
        return false;
    }

    @Override
    public String toString() {
        return "Course[" + courseId + "," + courseName + "," + courseType + "]";
    }
}

为什么要使用equals方法?另外,POJO和getters和setters是一样的吗? - Rishabh Agarwal

0
public class UserInfo {
        String LoginId;
        String Password;
        String FirstName;
        String LastName;
        String Email;
        String Mobile;
        String Address;
        String DOB;

        public String getLoginId() {
            return LoginId;
        }

        public void setLoginId(String loginId) {
            LoginId = loginId;
        }

        public String getPassword() {
            return Password;
        }

        public void setPassword(String password) {
            Password = password;
        }

        public String getFirstName() {
            return FirstName;
        }

        public void setFirstName(String firstName) {
            FirstName = firstName;
        }

        public String getLastName() {
            return LastName;
        }

        public void setLastName(String lastName) {
            LastName = lastName;
        }

        public String getEmail() {
            return Email;
        }

        public void setEmail(String email) {
            Email = email;
        }

        public String getMobile() {
            return Mobile;
        }

        public void setMobile(String mobile) {
            Mobile = mobile;
        }

        public String getAddress() {
            return Address;
        }

        public void setAddress(String address) {
            Address = address;
        }

        public String getDOB() {
            return DOB;
        }

        public void setDOB(String DOB) {
            this.DOB = DOB;
        }
    }

0
如果一个类没有被框架或库所束缚,那么从该类创建的对象被认为是POJO。
让我们看一些例子:
class MyServlet extends HttpServlet{
    //....
}

MyServlet类的唯一含义由HttpServlet类给出。因此,从MyServlet创建的对象不是POJO

class MyClass implements Serializable{
    //...
}

Serializable接口并不赋予MyClass类任何含义。因此,从MyClass创建的对象是POJO


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接