新闻资讯

新闻资讯 媒体报道

java 为什么有private关键字?

编辑:016     时间:2021-11-26


简单解释一下

题主描述了两种方式:

  1. public字段;
  2. private字段 + getter/setter;

这是两种外部访问对象的属性的方式。其实其区别已经很容易看出来了:

  1. 方案1中,只能读/写,而方案2中,不但可以读写,还可以加入权限判断、范围判断等等处理;
  2. 方案1中,读/写的权限是一样的(统统public,或者统统package),而方案2中,读/写的权限可以不一样(比如get是public的,set是package的);

方案1写着舒服,并且代码简洁,方案2明显功能要强的多。也就是说,存在着一些情况,你不得不按照方案2来实现。

而在实际应用中,我们很难在一开始就确定这个程序在将来的迭代中不会增加功能。也就是说,在开发的时候,方案1已经足够了,但是在迭代升级的时候,会发现方案1已经无法实现全部需求了,就需要改成方案2,而这个改动是十分麻烦的。所以我们在开发的时候,就直接采用方案2来开发。

直接采用方案2,当需求发生更改的时候,我们只需要修改getter/setter方法内部即可,而不需要修改使用这个类的代码,这就将代码的修改控制在很小的范围,这就是封装带来的好处。

举个例子。

你在为某农业大国的CDC写一个疫情信息公开系统,现在要写一个类,来描述某个地区疫情状况,类里包括地区名称,以及感染人数,你有两种实现方式:

A:

public class CovidInfo_TypeA { public final String placeName; public int infectedNumber; public CovidInfo_TypeA(String placeName, int infectedNumber) { this.placeName = placeName; this.infectedNumber = infectedNumber; } }

B:

public class CovidInfo_TypeB { private final String placeName; private int infectedNumber; public CovidInfo_TypeB(String placeName, int infectedNumber) { this.placeName = placeName; this.infectedNumber = infectedNumber; } public int getInfectedNumber() { return infectedNumber; } public void setInfectedNumber(int value) { infectedNumber = value; } public String getPlaceName() { return placeName; } }

然后用的时候就是这两种方式:

A:

import java.util.Scanner; public class UseCovidInfo_TypeA { public static void main(String[] args) { CovidInfo_TypeA info = new CovidInfo_TypeA("The Beautiful Country", 0); Scanner scanner = new Scanner(System.in); info.infectedNumber = scanner.nextInt(); System.out.println(info.infectedNumber); scanner.close(); } }

B:

import java.util.Scanner; public class UseCovidInfo_TypeB { public static void main(String[] args) { CovidInfo_TypeB info = new CovidInfo_TypeB("The Beautiful Country", 0); Scanner scanner = new Scanner(System.in); info.setInfectedNumber(scanner.nextInt()); System.out.println(info.getInfectedNumber()); scanner.close(); } }

你看,TypeB不仅写这个类的时候麻烦,用的时候也麻烦。那为什么还会有这种写法呢?

我们来看这样一个新的需求:

  1. 对于没有密码的使用方,只提供是否有感染病例,对于有密码的使用方,则提供详细病例;
  2. 如果感染病例数量增高,则有50%概率不变;
  3. 如果当地有感染病例,那么有50%概率将地区名称临时替换为CHINA!;

此时,如果是TypeB,就很好进行修改了:

import java.util.Random; public class CovidInfo_TypeB { private final String placeName; private int infectedNumber; public CovidInfo_TypeB(String placeName, int infectedNumber) { this.placeName = placeName; this.infectedNumber = infectedNumber; } public int getInfectedNumber() { return infectedNumber > 0 ? 1 : 0; } public int getInfectedNumber(String password) { if (PasswordValidator.getInstance().validate(password)) { return infectedNumber; } throw new RuntimeException("authorization error"); } public void setInfectedNumber(int value) { if (infectedNumber < value && new Random().nextDouble() < 0.5) { return; } infectedNumber = value; } public String getPlaceName() { if (infectedNumber > 0 && new Random().nextDouble() < 0.5) { return "CHINA!"; } return placeName; } }

而使用CovidInfo_TypeB类的地方根本不需要改动,非常的方便。

但是对于TypeA呢?似乎你需要手动查看哪里使用过CovidInfo_TypeA类,然后手动添加上判断代码。要么就是把TypeA改成TypeB的实现方式,然后把所有对TypeA直接访问字段的地方改成调用getter/setter方法,但无论如何,都需要修改使用这个类的代码。

这还算轻的,如果使用TypeA的,是另一个部门,甚至你这些东西是作为一个类库提供的,你又要怎么去修改使用CovidInfo_TypeA类的代码呢?

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

回复列表

相关推荐