如何用Java封装数组
我从Java开始,学习setter、getter和封装。我有一个非常简单的程序,分为两类:如何用Java封装数组,java,arrays,encapsulation,getter,Java,Arrays,Encapsulation,Getter,我从Java开始,学习setter、getter和封装。我有一个非常简单的程序,分为两类: Container有一个带有setter和getter的私有int数组(numArray) Main创建一个Container对象,并在totalArray方法中使用它 公共类容器{ private int numArray[]={0,0,0}; 公共int[]getNumArray(){ 返回努马拉; } 公共void setNumArray(int索引,int值){ Numaray[指数]=数值
有一个带有setter和getter的私有int数组(Container
)numArray
创建一个Main
对象,并在Container
方法中使用它totalArray
公共类容器{
private int numArray[]={0,0,0};
公共int[]getNumArray(){
返回努马拉;
}
公共void setNumArray(int索引,int值){
Numaray[指数]=数值;
}
}
公共班机{
公共静态void main(字符串[]args){
容器内容=新容器();
System.out.println(totalArray(conte.getNumArray());
conte.getNumArray()[2]++;
System.out.println(totalArray(conte.getNumArray());
}
专用静态整数totalArray(整数v[]{
int-total=0;
对于(int conta=0;conta,您通常会查看您试图向类的调用者提供的接口
方法如下:
void addItem(Object item);
Object getItem(int index);
int getSize();
是您将在容器类中提供的类型。然后它们代表调用方与私有数组交互
如果希望返回整个数组而不允许更改,可以在getter中将数组复制到新数组中并返回副本
或者,如果使用Java集合类而不是基元数组,则它们会提供一个不可修改的xxx()方法(例如,Collections.unmodifiableList(myList)
)它为集合提供了一个只读包装。要防止人们更改数组,您所能做的就是在getter中提供它的副本
public int[] getArray() {
return Arrays.copyOf(numArray, numArray.length);
}
通过这种方式,其他方法可以更改自己的数组副本,但是当它们再次调用getter时,它们会得到原始版本,没有更改。只有您提供的setNumArray()
可以实际修改您的内部数组
否则,如果要完全阻止容器,则必须删除数组并使用不可变对象。库提供不可变列表,或使用。如果要返回数组,请克隆它:
public int[] getArray() {
return (int[]) numArray.clone();
}
在公共API中,您应该确保向调用者清楚地记录这一点(实际上,无论哪种方式,如果调用者得到的数组是否会改变类的状态,他们都需要知道).封装是隐藏实现的过程。集合是否将其数据存储在数组中是一个实现细节;如果它被封装,您将希望能够将其更改为其他存储类型
您正在公开状态(或派生状态)的事实本身因为getter和setter会破坏封装,并暗示您正在实现抽象数据类型,而不是真正的面向对象类。例如,ArrayList
是一种数据类型,它不表示应用程序中任何真正的行为封装。这是否是您想要的,取决于该类型的使用方式和位置d
我倾向于使<代码>容器实现代码> >迭代-<代码>,如果它只是一个容器数据类型,或者提供一个内部迭代器方法,如果它是一个封装类,则传递一个访问者。如果它是抽象数据类型,则强烈地考虑使用内置的代码,如<代码> INT[]。
或列表
。还有另一种方法,它不复制阵列,但有其他缺点。我会将其用于非常大的阵列:
private A[] items;
public List<A> getItems() {
return Collections.unmodifiableList(Arrays.asList(items));
}
private A[]项目;
公共列表getItems(){
返回集合.unmodifiableList(Arrays.asList(items));
}
我想建议一种不同于我在这里看到的所有答案的方法。在考虑封装时,也可以考虑“不要向对象请求数据,请对象为您操作其数据”的规则
您没有让我使用numArray
,我将假设您的目标是从数学(而不是Java向量)创建一个数字“向量”,以用于示例目的
因此,您创建了一个包含一个双精度数组的NumericVector类。您的NumericVector将使用类似于multiplyByScalar(双精度标量)
和addVector(NumericVector secondVector)的方法来添加元素
您的内部数组是完全封装的-它永远不会逃逸。对它所做的任何操作都是通过这些“业务方法”在NumericVector类中完成的。在对它进行操作后,您如何显示它?让NumericVector覆盖NumericVector.toString()
,以便它正确打印出来,或者如果您有GUI,编写一个“控制器”类将数据从模型(NumbericVector)传输到视图(GUI)。这可能需要一种从NumbericVector流式传输元素的方法
这也表明了一些需要避免的事情:不要自动创建setter和getter,它们会破坏您的封装。您通常需要getter,但正如其他人所说的,您应该让getter返回数组的不可变版本。同时尽可能使类不可变。我前面提到的方法<代码>numericVector.addVector(numericVector secondVector)可能不应修改numericVector
,而应随解决方案返回新的numericVector
这种方法(通常是OO)经常失败的情况是库——当你真的想给数组添加一点功能,但仍然把它作为一个通用数组。在这种情况下,Java通常根本不关心封装,它只是添加了一个可以为集合/数组做些事情的助手方法/类(请看“Arrays”对象(有很多很好的例子)
如何用Java封装数组
问题可能已经很清楚了,但是我想OOP的重点是将类设计为一个操作
private A[] items;
public List<A> getItems() {
return Collections.unmodifiableList(Arrays.asList(items));
}
package com.eric.stackoverflow.example;
import java.util.List;
import com.google.common.collect.ImmutableList;
public class Container {
private int numArray[] = {0, 0, 0};
public int[] getNumArray() {
return ImmutableList.copyOf(numArray);
}
public void setNumArray(int index, int value) {
numArray[index] = value;
}
}