Java程序员初学者需要注意什么(初级Java程序员需要注意的问题)

  • 时间:
  • 8767人关注

这是一篇关于java相关的编程问答内容,被341位程序员关注,内容涉及到Java程序员、Java注意、初级Java程序员需要注意的问题等,由靳柔谨 编辑补充,一起来看下大家的回答。

初级Java程序员处于知识吸纳以及实战应用的过渡环节,这个过程决定了一个Java程序员未来的职场发展之路。很多人因为没有避免某些坑,而最终在短短几年内遇到的职场发展瓶颈最终终结了自己的开发之路。那初级Java程序员需要注意哪些问题呢? 

1、时刻提醒自己Java是一种OOP语言工具,而不仅仅是编码,只有这样才能总体把握和运用Java。

2、在学习的过程中,最好能够了解Java的底层机制,而不是仅仅停留在表层,不是抄书上的例子运行出结果就可以。要注意,即便对一个简单的例子也要有耐心去琢磨、调试、改动。

3、在学习的过程中一定要动手做、写代码,而不是抱一本书看看就行。很多东西和体会必须自己动手才能真正属于自己,最好能参与一些实际的项目。

4、在学到一定阶段后,你开始希望用学过的东西做些什么。这时的你应该开始学习一些更多、更复杂的知识,比如J2EE平台的构建、EJB的开发等。对于知识复杂多的内容,我们可以选择相应的书籍进行学习,当然最好、最节时、最有效的方法就行选择专业的培训机构进行系统学习java课程。

这里主要为大家整理了四条关于初级的Java程序员应该注意的那些问题。在实际的学习工作中, 仅仅将Java当做工具使用,虽然可以应付企业最基础的开发需求,但是因为不懂原理,没有吸收学习更多的新知识,最终是会被职场所淘汰。

码农之家
精选回答2:如何从Java程序员到Java架构师

21小时43分钟前回答

怎样学习才能从一名Java初级程序员成长为一名合格的架构师,或者说一名合格的架构师应该有怎样的技术知识体系,这是不仅一个刚刚踏入职场的初级程序员也是工作三五年之后开始迷茫的老程序员经常会问到的问题。希望这篇文章会是你看到过的最全面最权威的回答。

一、JAVA。要想成为JAVA(高级)专家肯定要学习JAVA。一般的程序员或许只需知道一些JAVA的语法结构就可以应付了。但要成为JAVA(高级)专家,您要对JAVA做比较深入的研究。您应该多研究一下JDBC、IO包、源码分析、高并发、JMS、Spring、RMI、线程。如果可能,希望您对JAVA的所有包都浏览一下,知道大概的API,这样您就发现其实您想实现的很多功能,通过JAVA的API都可以实现了,就不必自己费太多的脑经了。

二、设计模式。其实写代码是很容易的事情,我相信您也有同感。但如何写得好就比较难了。这个“好”字包括代码可重用性,可维护性,可扩展性等。如何写出好的代码往往要借助一些设计模式。当然长期的代码经验积累,只要您用心,会使您形成自己代码风格。相信您的代码也比较符合代码的可重用性,可维护性,可扩展性。但既然前人已经给我们总结出了经验,我们何不踩着前人的肩膀前进?

三、XML。现在的系统中不使用XML几乎是不可能的。XML的功能非常强大,它可以做数据转换、做系统的配置、甚至可保存您的系统业务数据。因此您必须了解XML,包括它的语法,结构。您还需要比较熟练的使用解析XML的一些API,比如JDOM,SAX等,因为在我们一般的项目中,XML往往担当系统配置信息的作用,您需要用这些API解析这些配置信息,开发完美的项目。

四、精通使用一种或两种框架。像在《如何成为高薪架构师》中提到的那样,“框架都会有许多可重用的代码,良好的层次关系和业务控制逻辑,基于框架的开发使你可以省出很多的开发成本”。但我这里希望您能精通,更多的是希望您能通过框架的使用了解框架的思想。这样您在开发一个项目时思路会开阔一些,比如您会想到把SQL语句与您的JAVA代码分开,再比如您会考虑把您的业务逻辑配置到XML或者数据库中,这样整个项目就很容易扩张了。

五、熟悉主流数据库。其实真正比较大的项目都是有人专门做数据库的,但往往很多项目要求作为(高级)工程师的您也参与数据库的设计以及SQL的编写。所以为了更好的为国家做贡献,建议您还是多了解一些主流数据库,比如SQLSERVER,ORACLE,多连接SQL和存储过程以及触发器。如果您不是“科班”出身,您还需要补充一些数据库原理方面的知识。

六、UML。我知道您肯定想成为高级工程师,因此您有必要了解或熟练或精通UML,这取决于您有多大决心想成为高级工程师和项目经理。在比较正规的开发团队中,UML是讨论项目的交流工具,您要想做一个软件工程师,您至少要能看懂,您要想做高级工程师,您要能通过它来描述您对项目的理解,尽管这不是必须,但却很重要。

七、站在高度分析问题:这不是一个知识点,也不是通过书本就能学得到的。只所以提到这一点,是因为我比您还着急,我希望您更快的成为一个高级的软件工程师,而不是一个一般的软件工程师。希望您在工作中多向您的系统分析员、需求分析员、系统设计员学习,多站在他们角度上去看您在开发的项目。在最好在项目之初先在您的脑海里对项目有个大致的分析、设计,然后和他们进行比较,找找差别,想想缺点。

八、工具。与在《Java程序员的未来发展之路,你是否感到迷茫?》里提到的不同,您在这个阶段可能接触到不同的工具了,尽管您还需要使用JB或者IDEA,但能可能对ROSE,Together要多了解一些,因为您要画UML了。不要再对Dreamweaver等HTML编辑器情有独钟了,那些JSP页面让初级程序员去写吧

Java进阶技术方面

据不完全统计,截至目前(2017.07)为止,中国Java程序员的数量已经超过了100万。而且,随着IT培训业的持续发展和大量的应届毕业生进入社会,Java程序员面临的竞争压力越来越大。那么,作为一名Java程序员,怎样努力才能快速成长为一名高级的程序员或者架构师,或者说一名优秀的高级工程师或架构师应该有怎样的技术知识体系,这不仅是一个刚刚踏入职场的初级程序员,也是工作三五年之后开始迷茫的老程序员,都必须要面对和想明白的问题。为了帮助大家少走弯路,我们总结出一个Java程序员的工作2-5年成长路线图。

展开问题
码农之家
精选回答3:java程序员必须知道的4个书写代码技巧

17小时20分钟前回答

如果现在要求对你写的Java代码进行优化,那你会怎么做呢?作者在本文介绍了可以提高系统性能以及代码可读性的四种方法,如果你对此感兴趣,就让我们一起来看看吧。

我们平时的编程任务不外乎就是将相同的技术套件应用到不同的项目中去,对于大多数情况来说,这些技术都是可以满足目标的。然而,有的项目可能需要用到一些特别的技术,因此工程师们得深入研究,去寻找那些最简单但最有效的方法。在以前一篇文章中,我们讨论了必要时可以使用的四种特殊技术,这些特殊技术可以创建更好的Java软件;而本文我们将介绍一些有助于解决常见问题的通用设计策略和目标实现技术,即:

只做有目的性的优化

常量尽量使用枚举

重新定义类里面的equals()方法

尽量多使用多态性

值得注意的是,本文中描述的技术并不是适用于所有情况。另外这些技术应该什么时候使用以及在什么地方使用,都是需要使用者经过深思熟虑的。

1 .只做有目的性的优化

大型软件系统肯定非常关注性能问题。虽然我们希望能够写出最高效的代码,但很多时候,如果想对代码进行优化,我们却无从下手。例如,下面的这段代码会影响到性能吗?

public void processIntegers(List<Integer> integers) {

  for (Integer value: integers) {
    for (int i = integers.size() - 1; i >= 0; i--) {
      value += integers.get(i);
    }
  }
}

这就得视情况而定了。上面这段代码可以看出它的处理算法是O(n³)(使用大O符号),其中n是list集合的大小。如果n只有5,那么就不会有问题,只会执行25次迭代。但如果n是10万,那可能会影响性能了。请注意,即使这样我们也不能判定肯定会有问题。尽管此方法需要执行10亿次逻辑迭代,但会不会对性能产生影响仍然有待讨论。

例如,假设客户端是在它自己的线程中执行这段代码,并且异步等待计算完成,那么它的执行时间有可能是可以接受的。同样,如果系统部署在了生产环境上,但是没有客户端进行调用,那我们根本没必要去对这段代码进行优化,因为压根就不会消耗系统的整体性能。事实上,优化性能以后系统会变得更加复杂,悲剧的是系统的性能却没有因此而提高。

最重要的是天下没有免费的午餐,因此为了降低代价,我们通常会通过类似于缓存、循环展开或预计算值这类技术去实现优化,这样反而增加了系统的复杂性,也降低了代码的可读性。如果这种优化可以提高系统的性能,那么即使变得复杂,那也是值得的,但是做决定之前,必须首先知道这两条信息:

性能要求是什么

性能瓶颈在哪里

首先我们需要清楚地知道性能要求是什么。如果最终是在要求以内,并且最终用户也没有提出什么异议,那么就没有必要进行性能优化。但是,当添加了新功能或者系统的数据量达到一定规模以后就必须进行优化了,否则可能会出现问题。

在这种情况下,不应该靠直觉,也不应该依靠检查。因为即使是像Martin Fowler这样有经验的开发人员也容易做一些错误的优化,正如在重构(第70页)一文中解释的那样:

如果分析了足够多的程序以后,你会发现关于性能的有趣之处在于,大部分时间都浪费在了系统中的一小部分代码中里面。如果对所有代码进行了同样的优化,那么最终结果就是浪费了90%的优化,因为优化过以后的代码运行得频率并不多。因为没有目标而做的优化所耗费的时间,都是在浪费时间。

作为一名身经百战的开发人员,我们应该认真对待这一观点。第一次猜测不仅没有提高系统的性能,而且90%的开发时间完全是浪费了。相反,我们应该在生产环境(或者预生产环境中)执行常见用例,并找出在执行过程中是哪部分在消耗系统资源,然后对系统进行配置。例如消耗大部分资源的代码只占了10%,那么优化其余90%的代码就是浪费时间。

根据分析结果,要想使用这些知识,我们应该从最常见的情况入手。因为这将确保实际付出的努力最终是可以提高系统的性能。每次优化后,都应该重复分析步骤。因为这不仅可以确保系统的性能真的得到了改善,也可以看出再对系统进行优化后,性能瓶颈是在哪个部分(因为解决完一个瓶颈以后,其它瓶颈可能消耗系统更多的整体资源)。需要注意的是,在现有瓶颈中花费的时间百分比很可能会增加,因为剩下的瓶颈是暂时不变的,而且随着目标瓶颈的消除,整个执行时间应该会减少。

尽管在Java系统中想要对概要文件进行全面检查需要很大的容量,但是还是有一些很常见的工具可以帮助发现系统的性能热点,这些工具包括JMeter、AppDynamics和YourKit。另外,还可以参见DZone的性能监测指南,获取更多关于Java程序性能优化的信息。

虽然性能是许多大型软件系统一个非常重要的组成部分,也成为产品交付管道中自动化测试套件的一部分,但是还是不能够盲目的且没有目的的进行优化。相反,应该对已经掌握的性能瓶颈进行特定的优化。这不仅可以帮助我们避免增加了系统的复杂性,而且还让我们少走弯路,不去做那些浪费时间的优化。

2.常量尽量使用枚举

需要用户列出一组预定义或常量值的场景有很多,例如在web应用程序中可能遇到的HTTP响应代码。最常见的实现技术之一是新建类,该类里面有很多静态的final类型的值,每个值都应该有一句注释,描述该值的含义是什么:

public class HttpResponseCodes {
  public static final int OK = 200;
  public static final int NOT_FOUND = 404;
  public static final int FORBIDDEN = 403;
}
if (getHttpResponse().getStatusCode() == HttpResponseCodes.OK) {
  // Do something if the response code is OK 
}

能够有这种思路就已经非常好了,但这还是有一些缺点:

没有对传入的整数值进行严格的校验

由于是基本数据类型,因此不能调用状态代码上的方法

在第一种情况下只是简单的创建了一个特定的常量来表示特殊的整数值,但并没有对方法或变量进行限制,因此使用的值可能会超出定义的范围。例如:

public class HttpResponseHandler {
  public static void printMessage(int statusCode) {
    System.out.println("Recieved status of " + statusCode); 
  }
}
HttpResponseHandler.printMessage(15000);

尽管15000并不是有效的HTTP响应代码,但是由于服务器端也没有限制客户端必须提供有效的整数。在第二种情况下,我们没有办法为状态代码定义方法。例如,如果想要检查给定的状态代码是否是一个成功的代码,那就必须定义一个单独的函数:

public class HttpResponseCodes {
  public static final int OK = 200;
  public static final int NOT_FOUND = 404;
  public static final int FORBIDDEN = 403;
  public static boolean isSuccess(int statusCode) {
    return statusCode >= 200 && statusCode < 300; 
  }
}
if (HttpResponseCodes.isSuccess(getHttpResponse().getStatusCode())) {
  // Do something if the response code is a success code 
}

为了解决这些问题,我们需要将常量类型从基本数据类型改为自定义类型,并只允许自定义类的特定对象。这正是Java枚举(enum)的用途。使用enum,我们可以一次性解决这两个问题:

public enum HttpResponseCodes {
  OK(200),
  FORBIDDEN(403),
  NOT_FOUND(404);
  private final int code; 
  HttpResponseCodes(int code) {
    this.code = code;
  }
  public int getCode() {
    return code;
  }
  public boolean isSuccess() {
    return code >= 200 && code < 300;
  }
}
if (getHttpResponse().getStatusCode().isSuccess()) {
  // Do something if the response code is a success code 
}

同样,现在还可以要求在调用方法的时候提供必须有效的状态代码:

public class HttpResponseHandler {
  public static void printMessage(HttpResponseCode statusCode) {
    System.out.println("Recieved status of " + statusCode.getCode()); 
  }
}
HttpResponseHandler.printMessage(HttpResponseCode.OK);

值得注意的是,举这个例子事项说明如果是常量,则应该尽量使用枚举,但并不是说什么情况下都应该使用枚举。在某些情况下,可能希望使用一个常量来表示某个特殊值,但是也允许提供其它的值。例如,大家可能都知道圆周率,我们可以用一个常量来捕获这个值(并重用它):

public class NumericConstants {
  public static final double PI = 3.14;
  public static final double UNIT_CIRCLE_AREA = PI * PI;
}
public class Rug {
  private final double area;
  public class Run(double area) {
    this.area = area;
  }
  public double getCost() {
    return area * 2;
  }
}
// Create a carpet that is 4 feet in diameter (radius of 2 feet)
Rug fourFootRug = new Rug(2 * NumericConstants.UNIT_CIRCLE_AREA);

因此,使用枚举的规则可以归纳为:

当所有可能的离散值都已经提前知道了,那么就可以使用枚举

再拿上文中所提到的HTTP响应代码为例,我们可能知道HTTP状态代码的所有值(可以在RFC 7231中找的到,它定义了HTTP 1.1协议)。因此使用了枚举。在计算圆周率的情况下,我们不知道关于圆周率的所有可能值(任何可能的double都是有效的),但同时又希望为圆形的rugs创建一个常量,使计算更容易(更容易阅读);因此定义了一系列常量。

如果不能提前知道所有可能的值,但是又希望包含每个值的字段或方法,那么最简单的方法就是可以新建一个类来表示数据。尽管没有说过什么场景应该绝对不用枚举,但要想知道在什么地方、什么时间不使用枚举的关键是提前意识到所有的值,并且禁止使用其他任何值。

3.重新定义类里面的equals()方法

对象识别可能是一个很难解决的问题:如果两个对象在内存中占据相同的位置,那么它们是相同的吗?如果它们的id相同,它们是相同的吗?或者如果所有的字段都相等呢?虽然每个类都有自己的标识逻辑,但是在系统中有很多西方都需要去判断是否相等。例如,有如下的一个类,表示订单购买…

public class Purchase {
  private long id;
  public long getId() {
    return id;
  }
  public void setId(long id) {
    this.id = id;
  }
}

……就像下面写的这样,代码中肯定有很多地方都是类似于的:

Purchase originalPurchase = new Purchase();
Purchase updatedPurchase = new Purchase();
if (originalPurchase.getId() == updatedPurchase.getId()) {
  // Execute some logic for equal purchases 
}

这些逻辑调用的越多(反过来,违背了DRY原则),Purchase

类的身份信息也会变得越来越多。如果出于某种原因,更改了Purchase

类的身份逻辑(例如,更改了标识符的类型),则需要更新标识逻辑所在的位置肯定也非常多。

我们应该在类的内部初始化这个逻辑,而不是通过系统将Purchase类的身份逻辑进行过多的传播。乍一看,我们可以创建一个新的方法,比如isSame,这个方法的入参是一个Purchase对象,并对每个对象的id进行比较,看看它们是否相同:

public class Purchase {
  private long id;
  public boolean isSame(Purchase other) {
    return getId() == other.gerId();  
  }
}

虽然这是一个有效的解决方案,但是忽略了Java的内置功能:使用equals方法。Java中的每个类都是继承了Object类,虽然是隐式的,因此同样也就继承了equals方法。默认情况下,此方法将检查对象标识(内存中相同的对象),如JDK中的对象类定义(version 1.8.0_131)中的以下代码片段所示:

public boolean equals(Object obj) {
return (this == obj);
}

这个equals方法充当了注入身份逻辑的自然位置(通过覆盖默认的equals实现):

public class Purchase {
  private long id;
  public long getId() {
    return id;
  }
  public void setId(long id) {
    this.id = id;
  }
  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }
    else if (!(other instanceof Purchase)) {
      return false;
    }
    else {
      return ((Purchase) other).getId() == getId();
    }
  }
}

虽然这个equals方法看起来很复杂,但由于equals方法只接受类型对象的参数,所以我们只需要考虑三个案例:

另一个对象是当前对象(即originalPurchase.equals(originalPurchase)),根据定义,它们是同一个对象,因此返回true
另一个对象不是Purchase对象,在这种情况下,我们无法比较Purchase的id,因此,这两个对象不相等

其他对象不是同一个对象,但却是Purchase的实例,因此,是否相等取决于当前Purchase的id和其他Purchase是否相等
现在可以重构我们之前的条件,如下:

Purchase originalPurchase = new Purchase();
Purchase updatedPurchase = new Purchase();
if (originalPurchase.equals(updatedPurchase)) {
  // Execute some logic for equal purchases 
}

除了可以在系统中减少复制,重构默认的equals方法还有一些其它的优势。例如,如果构造一个Purchase对象列表,并检查列表是否包含具有相同ID(内存中不同对象)的另一个Purchase对象,那么我们就会得到true值,因为这两个值被认为是相等的:

List<Purchase> purchases = new ArrayList<>();
purchases.add(originalPurchase);
purchases.contains(updatedPurchase); // True

通常,无论在什么地方,如果需要判断两个类是否相等,则只需要使用重写过的equals方法就可以了。如果希望使用由于继承了Object对象而隐式具有的equals方法去判断相等性,我们还可以使用= =操作符,如下:

if (originalPurchase == updatedPurchase) {
  // The two objects are the same objects in memory 
}

还需要注意的是,当equals方法被重写以后,hashCode方法也应该被重写。有关这两种方法之间关系的更多信息,以及如何正确定义hashCode

方法,请参见此线程。

正如我们所看到的,重写equals方法不仅可以将身份逻辑在类的内部进行初始化,并在整个系统中减少了这种逻辑的扩散,它还允许Java语言对类做出有根据的决定。

4.尽量多使用多态性

对于任何一门编程语言来说,条件句都是一种很常见的结构,而且它的存在也是有一定原因的。因为不同的组合可以允许用户根据给定值或对象的瞬时状态改变系统的行为。假设用户需要计算各银行账户的余额,那么就可以开发出以下的代码:

public enum BankAccountType {
  CHECKING,
  SAVINGS,
  CERTIFICATE_OF_DEPOSIT;
}
public class BankAccount {
  private final BankAccountType type;
  public BankAccount(BankAccountType type) {
    this.type = type;
  }
  public double getInterestRate() {
    switch(type) {
      case CHECKING:
        return 0.03; // 3%
      case SAVINGS:
        return 0.04; // 4%
      case CERTIFICATE_OF_DEPOSIT:
        return 0.05; // 5%
      default:
        throw new UnsupportedOperationException();
    }
  }
  public boolean supportsDeposits() {
    switch(type) {
      case CHECKING:
        return true;
      case SAVINGS:
        return true;
      case CERTIFICATE_OF_DEPOSIT:
        return false;
      default:
        throw new UnsupportedOperationException();
    }
  }
}

虽然上面这段代码满足了基本的要求,但是有个很明显的缺陷:用户只是根据给定帐户的类型决定系统的行为。这不仅要求用户每次要做决定之前都需要检查账户类型,还需要在做出决定时重复这个逻辑。例如,在上面的设计中,用户必须在两种方法都进行检查才可以。这就可能会出现失控的情况,特别是接收到添加新帐户类型的需求时。

我们可以使用多态来隐式地做出决策,而不是使用账户类型用来区分。为了做到这一点,我们将BankAccount的具体类转换成一个接口,并将决策过程传入一系列具体的类,这些类代表了每种类型的银行帐户:

/**
 * Java学习交流QQ群:589809992 我们一起学Java!
 */
public interface BankAccount {
  public double getInterestRate();
  public boolean supportsDeposits();
}
public class CheckingAccount implements BankAccount {
  @Override
  public double getIntestRate() {
    return 0.03;
  }
  @Override
  public boolean supportsDeposits() {
    return true;
  }
}
public class SavingsAccount implements BankAccount {
  @Override
  public double getIntestRate() {
    return 0.04;
  }
  @Override
  public boolean supportsDeposits() {
    return true;
  }
}
public class CertificateOfDepositAccount implements BankAccount {
  @Override
  public double getIntestRate() {
    return 0.05;
  }
  @Override
  public boolean supportsDeposits() {
    return false;
  }
}

这不仅将每个帐户特有的信息封装到了到自己的类中,而且还支持用户可以在两种重要的方式中对设计进行变化。首先,如果想要添加一个新的银行帐户类型,只需创建一个新的具体类,实现了BankAccount的接口,给出两个方法的具体实现就可以了。在条件结构设计中,我们必须在枚举中添加一个新值,在两个方法中添加新的case语句,并在每个case语句下插入新帐户的逻辑。

其次,如果我们希望在BankAccount接口中添加一个新方法,我们只需在每个具体类中添加新方法。在条件设计中,我们必须复制现有的switch语句并将其添加到我们的新方法中。此外,我们还必须在每个case语句中添加每个帐户类型的逻辑。

在数学上,当我们创建一个新方法或添加一个新类型时,我们必须在多态和条件设计中做出相同数量的逻辑更改。例如,如果我们在多态设计中添加一个新方法,我们必须将新方法添加到所有n个银行帐户的具体类中,而在条件设计中,我们必须在我们的新方法中添加n个新的case语句。如果我们在多态设计中添加一个新的account类型,我们必须在BankAccount接口中实现所有的m数,而在条件设计中,我们必须向每个m现有方法添加一个新的case语句。

虽然我们必须做的改变的数量是相等的,但变化的性质却是完全不同的。在多态设计中,如果我们添加一个新的帐户类型并且忘记包含一个方法,编译器会抛出一个错误,因为我们没有在我们的BankAccount接口中实现所有的方法。在条件设计中,没有这样的检查,以确保每个类型都有一个case语句。如果添加了新类型,我们可以简单地忘记更新每个switch语句。这个问题越严重,我们就越重复我们的switch语句。我们是人类,我们倾向于犯错误。因此,任何时候,只要我们可以依赖编译器来提醒我们错误,我们就应该这么做。

关于这两种设计的第二个重要注意事项是它们在外部是等同的。例如,如果我们想要检查一个支票帐户的利率,条件设计就会类似如下:

BankAccount checkingAccount = new BankAccount(BankAccountType.CHECKING);
System.out.println(checkingAccount.getInterestRate()); // Output: 0.03

相反,多态设计将类似如下:

BankAccount checkingAccount = new CheckingAccount();
System.out.println(checkingAccount.getInterestRate()); // Output: 0.03

从外部的角度来看,我们只是在BankAccount对象上调用getintereUNK()。如果我们将创建过程抽象为一个工厂类的话,这将更加明显:

public class ConditionalAccountFactory {
  public static BankAccount createCheckingAccount() {
     return new BankAccount(BankAccountType.CHECKING);
  }
}
public class PolymorphicAccountFactory {
  public static BankAccount createCheckingAccount() {
     return new CheckingAccount();
  }
}
// In both cases, we create the accounts using a factory
BankAccount conditionalCheckingAccount = ConditionalAccountFactory.createCheckingAccount();
BankAccount polymorphicCheckingAccount = PolymorphicAccountFactory.createCheckingAccount();
// In both cases, the call to obtain the interest rate is the same
System.out.println(conditionalCheckingAccount.getInterestRate()); // Output: 0.03
System.out.println(polymorphicCheckingAccount.getInterestRate()); // Output: 0.03

将条件逻辑替换成多态类是非常常见的,因此已经发布了将条件语句重构为多态类的方法。这里就有一个简单的例子。此外,马丁·福勒(Martin Fowler)的《重构》(p . 255)也描述了执行这个重构的详细过程。

就像本文中的其他技术一样,对于何时执行从条件逻辑转换到多态类,没有硬性规定。事实上,如论在何种情况下我们都是不建议使用。在测试驱动的设计中:例如,Kent Beck设计了一个简单的货币系统,目的是使用多态类,但发现这使设计过于复杂,于是便将他的设计重新设计成一个非多态风格。经验和合理的判断将决定何时是将条件代码转换为多态代码的合适时间。

结束语

作为程序员,尽管平常所使用的常规技术可以解决大部分的问题,但有时我们应该打破这种常规,主动需求一些创新。毕竟作为一名开发人员,扩展自己知识面的的广度和深度,不仅能让我们做出更明智的决定,也能让我们变得越来越聪明。

展开问题
码农之家
精选回答4:程序员入门Java零基础书籍

3小时51分钟前回答

有人说开卷有益,读万卷书行万里路;有人说,书不在多,精益求精;有人说,书读百遍,其义自现。其实每个人都有自己的读书计划和习惯,对于技能提升类的图书,建议还是多读经典和实战。

1.《深入理解Java虚拟机》

推荐:

围绕内存管理、执行子系统、编程编译与优化、高效并发等核心内容对JVM进行全面而深入的分析,深刻揭示JVM的工作原理

注重实现,以解决实践中的疑难问题为首要目的,包含大量经典案例和最佳实践

内容简介:

作为一位Java程序员,你是否也曾经想深入理解Java虚拟机,但是却被它的复杂和深奥拒之门外?没关系,《深入理解Java虚拟机:JVM高级特性与最佳实践》极尽化繁为简之妙,能带领你在轻松中领略Java虚拟机的奥秘。《深入理解Java虚拟机:JVM高级特性与最佳实践》是近年来国内出版的唯一一本与Java虚拟机相关的专著,也是唯一一本同时从核心理论和实际运用这两个角度去探讨Java虚拟机的著作,不仅理论分析得透彻,而且书中包含的典型案例和最佳实践也极具现实指导意义。

2.《零基础学Java(第4版)》

内容简介:

Java是目前最流行的开发语言之一,也是目前提供职位最多的开发语言之一。本书站在零基础学习的角度,使初学者能尽快掌握Java语言程序设计的精髓而少走弯路。

《零基础学Java(第4版)》一共分为四篇,共25章,循序渐进地讲述了Java语言的语法规则,以及Eclipse和MyEclipse开发环境的使用,从基本概念到具体实践、从入门知识到高阶主题、从语法语义到数据结构和算法都进行了详细的阐述,内容主要包括运算符、表达式、分支语句、循环语句、函数、数组、字符串、类、对象、包、继承、多态、封装、枚举、反射、标注、泛型、类加载器、动态代理、多线程、文件的操作和访问、数据的操作、数据的存储、Java数据结构、XML文件的创建和解析、数据库的连接、网络编程和界面的设计等知识点。

      以上就是码农之家Java培训机构小编介绍的“程序员入门Java零基础书籍”的内容,希望对大家有帮助,如有疑问,请在线咨询,有专业老师随时为你服务。

展开问题

参考资料

  • Java程序员职场全攻略:从小工到专家

    Java程序员职场全攻略:从小工到专家

    Java程序员职场全攻略 作者:吴亚峰著 ISBN:7121102463/9787121102462 出版时间:2010-2-1 丛编项:从小工到专家

    大小:39.38MBJava

    立即下载
  • Java程序员修炼之道

    Java程序员修炼之道

    伴随着关键服务平台及其生态体系的与时俱进,Java技术性一直在迅速往前发展趋势。《 Java程序员修炼之道 》包含了Java7的**特性和Java开发设计的核心技术,对当今很多开源系统技术性共存,

    大小:8.7 MBJava

    立即下载
  • 黑马程序员面试题汇总(java/数据库/前端)

    黑马程序员面试题汇总(java/数据库/前端)

    此套教程整理了网上总结的面试题,有java面试题,jq面试题,jsp、servlet、ajax面试题,mysql面试题,oracle面试题,redis教案,也有最近时间总结的公司面试题,涉及的层面虽然不是很多,但是应对面试 应该还是可以的。 文件夹大概有20兆的大小,所以面试题数量也是不少的,里面也包含了一些总结和见解,比如说在集合方面的知识点有实现的各自特点,他们之间的区别,以及等等原理和实现的细节,还包含了java和前端的面试宝典,一个宝典大概有500页左

    大小:20.4 MB程序员面试

    立即下载
  • Java程序员面试笔试宝典

    Java程序员面试笔试宝典

    本书是程序员求职面试笔试必备图书,以独特的视角对面试过程中求职者存在的各类问题进行了深度剖析,是一本适合计算机相关专业毕业生阅读的求职指导用书

    大小:73.4 MBJava面试

    立即下载
  • Java程序员面试笔试真题与解析

    Java程序员面试笔试真题与解析

    这是一本程序员面试笔试必读书籍,考查率高,本书中所选真题全是程序员面试笔试常考点,针对当前各大IT企业面试笔试中特性与侧重点,精心挑选了三年来近百家IT企业的面试笔试真题,欢

    大小:64.9 MB程序员面试

    立即下载
  • Java程序员面试笔试真题库

    Java程序员面试笔试真题库

    《Java程序员面试笔试真题库》 针对当前各大IT企业面试笔试中的特性与侧重点,精心挑选了近3年来18家IT企业的面试笔试真题,这些企业涉及业务包括系统软件、搜索引擎、电子商务、手机A

    大小:291.9 MBJava面试

    立即下载
  • Java程序员面试宝典

    Java程序员面试宝典

    Java程序员面试宝典(第4版) 是《Java程序员面试宝典》的第4版。第4版在保留前三版数据结构、字符串处理、Java程序设计等主干内容的基础上,更新了部分程序员面试题目,内容主要取材于

    大小:78.6 MBJava面试

    立即下载

更多回答

20小时8分钟前回答

初级程序员的几道Java编程思想练习题

1、编写程序实现对给定的4个整数从大到小的顺序排列。 package HomeWork01;import java.util.Scanner;public class HomeWork01 {static int number=4; //输入4个数存放在数组中static int[] t1 = new int[number];public static void main(String[] args) {HomeWork01 jiejie=new HomeWork01();jiejie.shunxun();}void shunxun(){System.out.println("请输入4个数:");Scanner in_t1 = new Scanner(System.in);//循环输入数组for(int i=0;it1[i]=in_t1.nextInt();}for (int i = 0; i  t1.length; i++) {int pos = i;for (int j = i + 1; j  t1.length; j++) {if (t1[pos]  t1[j])pos = j;}if (pos != i) {t1[i] = t1[i] + t1[pos];t1[pos] = t1[i] - t1[pos];t1[i] = t1[i] - t1[pos];}}for (int i = t1.length - 1; i = 0; i……

7小时20分钟前回答

程序员面试掌握的Java笔试面试题

面试Java开发的求职者要想从众多的优秀者脱颖而出并不容易,因此小编专门汇总了程序员面试掌握的Java笔试面试题,希望能让大家在面试前做好更充足的准备。 1、hread类的start()和run()方法的区别。 答案:start()方法会创建新的线程并启动该线程,所以该方法会调用其他native方法,而run()方法就是:正常的Java方法调用,即在原来的线程中执行java代码。 2、Java中Runnable和Callable的区别。 答案:Runnable和Callable都代表要线程中执行的任务。Runnable是JDK1.0加入的,而Callable确实是在JDK1.5加入的。区别:Callable的call()方法可以返回值和抛出异常,而Runnable的run()方法不能返回值也不能抛出异常。Callable是需要使用ja……