Java

Hire the Top 3% of 自由Java开发人员

Toptal是面向顶级Java开发人员的市场, contractors, engineers, programmers, coders, architects, and consultants. 顶级公司和初创公司选择Toptal Java自由职业者来完成他们的关键任务软件项目.

无风险试用,满意才付款.

Clients Rate Java开发人员总数4.5 / 5.0截至2023年12月28日,平均有1344条评论

雇佣自由Java开发人员和工程师

Julie Wetherbee

自由Java开发人员

United StatesToptal的自由Java开发人员 Since August 21, 2015

Julie在为各种规模的企业构建软件应用程序和领导工程团队方面拥有超过20年的经验. 她是Java方面的专家, JavaScript, C, C++, and Perl, 并且熟悉许多流行的框架. 最近,Julie为沃尔玛设计并实现了一个大规模的Oracle数据库分片解决方案.com.

Show More

Rizwan Rizvi

自由Java开发人员

United StatesToptal的自由Java开发人员 Since June 13, 2018

里兹万以通过清晰的思维克服复杂的挑战而闻名, 创新的方法, 加强组织不同部门之间的沟通. 在他的职业生涯中, 他优化了多样化和分散的IT专业人员团队的工作,并在具有挑战性的环境中始终如一地交付了有利可图的项目.

Show More

让Savard

自由Java开发人员

CanadaToptal的自由Java开发人员 Since March 24, 2016

jean - franois是一个充满激情的开发人员,他从14岁开始用Java编程,从那时起,他几乎没有一天不写代码. 尽管他在Java及其相关框架方面有独特的经验, 他对知识的渴望使他探索了计算机科学的几个方面, 比如机器学习, data science, 软件架构, 以及基于云的开发.

Show More

Claudio Aldana

自由Java开发人员

United StatesToptal的自由Java开发人员 Since September 12, 2018

Claudio是一位专注于业务成果的经验丰富的IT专家, 还有扎实的工程背景. 他运用数据科学来优化客户满意度, 产品个性化, and customer churn. Claudio也是一名认证的SharePoint专家,曾与微软的知名客户合作过, 帮助他们最大限度地提高安全性, performance, and usability.

Show More

Radek Ostrowski

自由Java开发人员

ThailandToptal的自由Java开发人员 Since September 24, 2014

Radek是Toptal区块链认证工程师,对以太坊和智能合约特别感兴趣. 在法币领域,他在大数据和机器学习项目方面经验丰富. 他是两次不同的国际IBM Apache Spark竞赛的三连冠得主, PlayStation 4后端的共同创造者, 一个成功的黑客马拉松选手, 并在澳大利亚的会议上发表演讲, Poland, and Serbia.

Show More

Luigi Crispo

自由Java开发人员

阿拉伯联合酋长国Toptal的自由Java开发人员 Since December 6, 2019

Luigi是一位经验丰富的云和领导力专家,在各种环境中拥有超过二十年的专业经验. 他对技术和价值驱动的项目充满热情,并且具有很强的适应能力. Luigi已经直接参与了一些推动数字时代的领导者的重大行业转型浪潮.

Show More

Bogdan Andrei-Teodor

自由Java开发人员

RomaniaToptal的自由Java开发人员 Since December 4, 2019

Bogdan是一名软件工程师,过去几年一直在游戏开发行业工作. 他的职业生涯开始于c++(前四年),然后转向Unity和c#(过去三年)。. Bogdan在企业和创业环境中都工作过,可以快速地将代码切换到其他语言(他有C语言的经验, Java, JavaScript, PHP, Python, and Bash/Batch).

Show More

Joanna Patrzyk

自由Java开发人员

PolandToptal的自由Java开发人员 Since November 29, 2019

乔安娜是一名软件工程师,在编程方面有八年多的经验. 她擅长构建全栈JavaScript解决方案,包括Node.js、TypeScript、React和React Native. Joanna在构建高质量的web、移动和PWA应用程序方面非常熟练.

Show More

Christina Lin

自由Java开发人员

CanadaToptal的自由Java开发人员 Since March 6, 2018

Christina是一名高级QA工程师,在测试自动化方面具有专业知识, test management, 以及对网络和移动应用程序的手动测试. 她在几个项目中使用Selenium WebDriver从头创建了测试自动化框架,并使用REST-assured和Postman自动化了API测试. 在私营和公共部门都有工作经验, 克里斯蒂娜曾与大型, medium-size, 小型创业公司.

Show More

Manuel Blechschmidt

自由Java开发人员

GermanyToptal的自由Java开发人员 Since November 2, 2020

Manuel是一名认证的Demandware开发人员和IT系统工程师. 他的专长是ERP和电子商务系统, 包括店铺设计, marketing, analytics, 物料管理, 生产计划. Manual已经为法国、比利时和美国的时尚零售商创建了多租户网站. 他曾在拉斯维加斯和阿姆斯特丹的SAP TechEds上发表演讲,并为以前的职位上的员工培训做出了贡献.

Show More

Juraj Kusnier

自由Java开发人员

GermanyToptal的自由Java开发人员 Since November 9, 2022

Juraj是一位经验丰富的高级软件工程师和Android应用开发者,专注于产品和高质量的用户体验. 在过去的10多年里, 他为大大小小的客户做过重要的项目, banks, 以及政府机构,并为数千万用户提供应用程序. Juraj知道如何处理大型遗留系统,以及如何快速有效地设置和启动绿地应用程序.

Show More

现在注册以查看更多资料.

Start Hiring
经常成对

获得额外的专业知识

我们的客户经常将这些额外的服务与我们的自由Java开发人员配对.

A Hiring Guide

雇用优秀Java开发人员指南

掌握Java是一项不小的壮举. 它的扩展类库包含了大量的功能和细微差别, 一般的开发者都忽略了其中的许多内容. 那些掌握了该语言的人可以对您的团队的生产力和系统的性能产生重大的积极影响. 这里有一些有针对性的问题,可以帮助你找到真正的语言大师.

Read Hiring Guide

Java招聘资源

Trustpilot
总体优势

在无风险试用后,98%的Toptal客户选择雇用我们的人才.

Toptal的筛选和匹配过程确保卓越的人才与您的精确需求相匹配.

Start Hiring
报纸上铺天盖地

... 允许公司快速组建具有特定项目所需技能的团队.

尽管对程序员的需求在不断增加,但Toptal对自己近乎常春藤联盟级别的审查感到自豪.

Our clients
为游戏制作应用程序
Conor Kenney
为游戏制作应用程序
构建一个跨平台的应用程序,在全球范围内使用
Thierry Jakicevic
构建一个跨平台的应用程序,在全球范围内使用
引领数字化转型
Elmar Platzer
引领数字化转型
挖掘实时数据将改变行业的游戏规则
挖掘实时数据将改变行业的游戏规则
Testimonials

没有Toptal就不会有Tripcents. Toptal Projects使我们能够与产品经理一起快速发展我们的基金会, lead developer, 高级设计师. 在60多天的时间里,我们从概念到Alpha. 其速度、知识、专业知识和灵活性是首屈一指的. Toptal团队是tripcents的一部分,就像tripcents的任何内部团队成员一样. 他们像其他人一样贡献并拥有开发的所有权. 我们将继续使用Toptal. 作为一家初创公司,它们是我们的秘密武器.

Brantley Pace, CEO & Co-Founder

Tripcents

我对我们与Toptal的合作经验非常满意. 和我一起工作的专业人员在几个小时内就和我通了电话. 在和他讨论了我的项目后,我知道他就是我想要的候选人. 我立即雇用了他,他没有浪费时间就完成了我的项目, 甚至通过添加一些很棒的设计元素来增加我们的整体外观.

保罗·芬利,局长

K Dunn & Associates

与我合作的开发者都非常出色——聪明、有动力、反应灵敏. 过去很难找到高质量的工程师和顾问. Now it isn't.

瑞安·洛克菲勒首席执行官

Radeeus

Toptal立即理解了我们的项目需求. 我们遇到了一位来自阿根廷的杰出自由职业者, from Day 1, 沉浸在我们的行业中, 与我们的团队无缝融合, 理解我们的愿景, 并产生了一流的结果. Toptal使与高级开发人员和程序员的联系变得非常容易.

Jason Kulik,联合创始人

ProHatch

作为一家资源有限的小公司,我们不能犯代价高昂的错误. Toptal为我们提供了一位经验丰富的程序员,他能够立即投入工作并开始做出贡献. 这是一次很棒的经历,我们会马上再来一次.

斯图尔特·波克尼校长

现场专用软件解决方案

我们使用Toptal聘请了一位具有丰富的Amazon Web Services经验的开发人员. 我们面试了四位候选人,其中一位非常符合我们的要求. 这个过程迅速而有效.

Abner Guzmán Rivera,首席技术官和首席科学家

Photo Kharma

Sergio是一个很棒的开发者. 一流,反应迅速,工作效率高.

Dennis Baldwin,首席技术专家和联合创始人

PriceBlink

和Marcin一起工作是一种乐趣. He is competent, professional, flexible, 并且非常迅速地理解需要什么以及如何实现它.

安德鲁·费舍尔,首席技术官

POSTIFY

我们需要一位能立即开始我们项目的专业工程师. 西马纳斯的工作超出了我们的预期. 不需要采访和追踪专家开发人员是一种非常节省时间的方法,并且让每个人都对我们选择切换平台以使用更健壮的语言感到更舒服. Toptal使这一过程变得简单方便. Toptal现在是我们寻求专家级帮助的首选之地.

Derek Minor, Web开发高级副总裁

网络传媒集团

Toptal的开发人员和架构师都非常专业,也很容易共事. 他们提供的解决方案价格合理,质量上乘,缩短了我们的发行时间. 再次感谢,Toptal.

首席执行官杰里米·韦塞尔斯

Kognosi

我们与Toptal合作非常愉快. 他们为我们的应用程序找到了完美的开发人员,让整个过程变得非常简单. 它也很容易超出最初的时间框架, 我们可以在整个项目中保持同一个承包商. 我们强烈推荐Toptal,因为它可以快速无缝地找到高素质的人才.

Ryan Morrissey,首席技术官

应用商业技术有限责任公司

我对Toptal印象深刻. 我们的开发人员每天都和我交流,他是一个非常强大的程序员. 他是一个真正的专业人士,他的工作非常出色. 5 stars for Toptal.

Pietro Casoar, CEO

Ronin Play Pty Ltd

与Toptal合作是一次很棒的经历. 在使用它们之前, 我花了相当多的时间面试其他自由职业者,但没有找到我需要的. 在与Toptal合作后,他们在几天内就为我找到了合适的开发者. 与我一起工作的开发人员不仅提供高质量的代码, 但他也提出了一些我没有想到的建议. 我很清楚,阿莫里知道自己在做什么. Highly recommended!

George Cheng, CEO

Bulavard, Inc.

作为一名Toptal合格的前端开发人员,我还经营着自己的咨询业务. 当客户来找我帮忙填补他们团队中的关键角色时, Toptal是我唯一愿意推荐的地方. Toptal的所有候选人都是精英中的精英. Toptal是我在近5年的专业在线工作中发现的性价比最高的网站.

Ethan Brooks, CTO

Langlotz Patent & 商标工程公司.

在希格尔的早期, 我们需要一流的开发者, 以可承受的价格, 及时地. Toptal delivered!

Lara Aldag, CEO

Higgle

Toptal能让你轻松找到合适的人选,让你放心,因为他们有能力. 我肯定会向任何寻找高技能开发人员的人推荐他们的服务.

Michael Gluckman,数据经理

Mxit

Toptal将我们的项目与最优秀的开发人员快速匹配的能力非常出色. 开发人员已经成为我们团队的一部分, 我对他们每个人所表现出的敬业精神感到惊讶. 对于那些希望与最好的工程师远程工作的人来说,没有比Toptal更好的了.

劳伦特·阿里,创始人

Livepress

Toptal让寻找合格的工程师变得轻而易举. 我们需要一个有经验的ASP.. NET MVC架构来指导我们的启动应用程序的开发, Toptal在不到一周的时间里为我们找到了三位优秀的候选人. 在做出我们的选择后,工程师立即在线并开始工作. 这比我们自己发现和审查候选人要快得多,也容易得多.

Jeff Kelly,联合创始人

协同解决方案

我们需要一些Scala的短期工作,Toptal在24小时内为我们找到了一位优秀的开发人员. 这在其他平台上是不可能实现的.

Franco Arda,联合创始人

WhatAdsWork.com

Toptal为快速发展和规模化的企业提供不妥协的解决方案. 我们通过Toptal签约的每一位工程师都迅速融入了我们的团队,并在保持惊人的开发速度的同时,将他们的工作保持在最高的质量标准.

Greg Kimball,联合创始人

nifti.com

如何通过Toptal招聘Java开发人员

1

与我们的行业专家交谈

Toptal的工程总监将与您一起了解您的目标, technical needs, and team dynamics.
2

与精心挑选的人才一起工作

几天之内,我们将为您的项目介绍合适的Java开发人员. 平均匹配时间在24小时以下.
3

绝对合适

与新的Java开发人员一起试用一段时间(只在满意的情况下付费), 在订婚前确保他们是合适的人选.

寻找拥有相关技能的专家

在我们的人才网络中访问大量熟练的开发人员,并在48小时内雇用最优秀的3%.

FAQs

  • total Java开发人员有何不同?

    At Toptal, 我们对Java开发人员进行了彻底的筛选,以确保我们只为您匹配最优秀的人才. 在200多个中,每年有5000人申请加入Toptal网络, 只有不到3%的人能达标. 你将与工程专家(而不是一般的招聘人员或人力资源代表)一起了解你的目标, technical needs, and team dynamics. 最终的结果是:经过专家审查的人才从我们的网络,定制匹配,以满足您的业务需求.

  • 我可以在48小时内通过Toptal雇佣远程Java开发人员吗?

    取决于可用性和进度, 您可以在注册后48小时内开始与Java开发人员合作.

  • Toptal Java开发人员的无风险试用期是什么?

    我们确保您和您的Java开发人员之间的每次约定都从长达两周的试用期开始. 这意味着你有时间确认订婚是否成功. 如果你对结果完全满意, 我们会给你开时间单的,你愿意多久我们就多久. 如果您不完全满意,我们不会向您收费. From there, 我们要么分道扬镳, 或者我们可以为您提供另一位可能更合适的专家,我们将与他开始第二轮谈判, no-risk trial.

Share
Java

如何聘请优秀的Java开发人员

The Challenge

今天,在它最初发布近20年后,据报道Java是世界上最伟大的语言 最受欢迎的语言技能,并且遥遥领先(受欢迎程度是亚军PHP的两倍)。.

Java应用程序的使用如此普遍, 简历上不乏会Java的开发人员. 但就像任何技术一样,首先要了解Java,然后 really knowing Java. 那么,如何才能确定谁是真正的Java开发专家呢?

Java mastery, 就像生活中的许多技能一样, 要充分利用它的力量需要时间和健康的好奇心. 因此,如我们的帖子所述 寻找少数精英, an effective recruiting process needs to evaluate many dimensions of a candidate beyond just technical knowledge; attributes such as drive, integrity, 创造力同样是一个软件开发大师的基本属性. 评估候选人的这些方面,然后可以用问题(例如本文中提出的问题)来扩充,以帮助确定哪些人是真正的高质量Java专家.

评估基金会

我们从一些问题开始,这些问题可以帮助评估候选人对一些基本Java范例和概念的理解深度.

问:什么是匿名类? 何时、为何以及如何使用它们? 提供一个示例.

匿名类是内联表达式, 为了方便,通常是一次性使用的类, 这有助于使您的代码更简洁. 下面的示例实例化了一个new ActionListener 处理与按钮相关的事件:

button.addActionListener(new ActionListener()) {
    公共无效actionPerformed(ActionEvent e) {
        /*响应按钮动作事件*/
    }
});

这是有意义的,因为类不在其他地方使用,也不需要名称. However, 如果将匿名类传递给注册方法, for instance, 您可能需要跟踪它的引用, 以便以后能够注销它. 让我们扩展上面的例子来演示这一点:

ActionListener = new ActionListener() {
    公共无效actionPerformed(ActionEvent e) {
        /*响应按钮动作事件*/
    };
button.addActionListener(听众);

/* some time later... */

button.removeActionListener(听众);

问:什么是抽象类? 何时、为何以及如何使用它们? 提供一个示例.

Abstract classes 是有用的定义抽象模板方法,具体子类必须实现. 因此,所有具体的子类都保证遵循由它们继承的抽象类中的抽象方法指定的API. 这在某种程度上类似于Java interface 为实现它的所有类指定一个API.

公共用例是指有一类对象具有共同的行为(例如.g., 所有形状都有一个面积), 但是计算或执行这些功能的细节因对象而异. For example:

 公共抽象类Shape {
     公共抽象双区();
 }
 
 公共类Circle extends Shape {
     专用双半径;
     
     公共圆(双半径){
         this.radius = radius;
     }
     public double area(){返回数学.PI * Math.pow(this.radius,2); }
 }
 
 公共类矩形扩展形状{
     私人双宽、高;
     
     公共矩形(双宽,双高){
         this.width = width;
         this.height = height;
     }
     Public double area(){返回这个.width * this.height; }
 }

以下几点值得注意:

  • Abstract classes may not be instantiated directly; only their concrete subclasses are instantiable.
  • 一个类可以被声明为抽象的,即使它没有抽象方法. 这将阻止该类被实例化. This can be useful, for example, 如果类层次结构中的基类没有抽象方法,但本身不打算被实例化.

问:比较和对比已检查和未检查的异常. Provide examples.

未经检查的异常 例外是 not 被认为是可恢复的. Java不会因为它们表示异常而强制您捕获或处理它们, 代码中的意外问题,例如 NullPointerException, ArithmeticException and IndexOutOfBoundsException. 也就是说,这些都是你需要修复或预防的问题. 未检查异常都派生自 RuntimeException.

Checked exceptions 例外情况是 are 被认为是可恢复的. Checked exceptions must explicitly be specified as part of a method’s API; that is, 可能抛出一个或多个受控异常的方法必须将这些潜在异常列为其方法声明的一部分(Java编译器实际上会强制执行这一点)。.

当调用引发异常的方法时,调用者必须处理(i.e.(捕获)这些异常,或者必须自己抛出它们. For example, 如果方法抛出检查异常, 调用者可能决定忽略错误并继续(吞下它), 向用户显示一个对话框, 或者重新抛出异常,让调用链更上层的方法处理它(在这种情况下,它还必须声明它抛出检查异常)。.

For example:

readFile(文件文件)抛出IOException, MyReadFileException {
    try {
        FileInputStream fis = new FileInputStream(file);
    } catch(FileNotFoundException e) {
        //捕获FileNotFoundException并抛出IOException;
        //所以我们没有在上面的"throws"子句中包含FileNotFoundException. 
        抛出新的IOException();
    }
    
    if (somethingBadHappened) {
        //我们在这里显式抛出自己的MyReadFileException,
        //所以我们把它包含在上面的"throws"子句中.
        抛出新的MyReadFileException();
    }
}

检查异常清楚地传达并强制处理错误条件. 然而,对于开发人员来说,不断地需要包含它也是一种痛苦 try/catch 块来处理来自它们调用的方法的所有已知异常. 尽管在Java中确实允许大量的检查异常, 事情可能会变得有点笨拙. For example:

抛出DataFormatException, InterruptedException, 
	IOException, SQLException, TimeoutException, ParseException {
...
}

因此,有 raging debate 例如,在编写库时是使用已检查异常还是未检查异常,多年来一直存在争议. 很多这样的辩论都是如此, 事实上,没有放之四海而皆准的方法, 全部正确答案. 检查异常和未检查异常各有优缺点, 因此,决定使用哪一种主要取决于情况和背景.

问:描述泛型,并提供Java中泛型方法和类的例子.

Java generics 使程序员能够指定, 使用单个方法或类声明, 可以应用于多种不同数据类型的功能. 泛型还提供编译时类型安全性,允许Java编程专家在编译时捕获无效类型.

例如,这里是a generic method that uses 作为泛型类型的占位符:

public  void printArray( E[] inputArray ) {
    //显示数组元素              
    for (E element: inputArray) {        
        System.out.Printf(“%s”,元素);
    }
    System.out.println();
}

The above method could then be invoked with various types of arrays and would handle them all appropriately; e.g.:

//使用Double数组调用printArray方法
Double[] doubleArray = {1.1, 2.2, 3.3, 4.4 };
printArray (doubleArray);

//使用字符数组调用通用printArray方法
字符[]charArray ={‘H’,‘E’,‘L’,‘L’,”O '};
printArray (charArray);

There may be times, though, 当您想要限制允许传递给泛型类型参数的类型类型时. For example, 对数字进行操作的方法可能只想接受Number或其子类的实例. 这是在一般情况下使用 有界型参数,其中列出了类型参数的名称,后面跟着 extends keyword. For example:

//确定三个可比对象中最大的
public static > T maximum(T x, T y, T z) {                      
  T max = x; // assume x is initially the largest       
  if ( y.compareTo( max ) > 0 ) {
     max = y; // y is the largest so far
  }
  if ( z.compareTo( max ) > 0 ) {
     max = z; // z is the largest now                 
  }
  return max; // returns the largest object   
}

与泛型方法一样,类的类型参数部分 generic class 可以使用逗号分隔一个或多个类型参数吗. For example:

public class Cell {
  private T val;

  public void set(T val){这个.val = val; }

  public T get() { return val; }

  public static void main(String[] args) {
     Cell integerCell = new Box();
     Cell stringCell = new Box();
    
     integerCell.(新添加整数(10));
     stringCell.add(new String("Hello World"));

     System.out.printf("整数值:%d\n\n", integerCell.get());
     System.out.printf("字符串值:%s\n", stringCell.get());
  }
}

问:什么是多重继承? 它有哪些潜在的问题?为什么Java传统上不支持它? 随着Java 8的发布,这种情况发生了什么变化?

多重继承 是一些面向对象的计算机编程语言的一个特征,其中一个对象或类可以从多个父对象或父类继承特征和功能. 它不同于单继承, 对象或类只能从一个特定的对象或类继承.

在Java 8之前,Java只支持单继承. 稍后我们将讨论Java 8对多重继承的准支持, 但是首先让我们了解多重继承会导致什么问题,以及为什么Java中极力避免多重继承.

反对多重继承的主要理由是复杂性, 潜在的模糊性, 它可以引入. 最典型的例子就是人们常说的“钻石问题”。, B类和C类继承于A类, 类D同时继承类B和类C. 如果a中的方法被B和C都重写了,就会产生歧义. If D does not override it, then which version of the method does it inherit; that of B, or that of C?

让我们考虑一个简单的例子. 一所大学有附属于它的人. 有些是学生,有些是教员,有些是管理人员,等等. 因此,一个简单的继承方案可能有不同类型的人担任不同的角色, 所有这些都继承自一个共同的“Person”类. Person类可以定义一个抽象 getRole() 方法,然后由其子类重写该方法以返回正确的角色类型.e.:

但是如果我们想要模拟助教的角色会发生什么呢?? Typically, a TA is both a grad student and a faculty member. 这就产生了多重继承的经典菱形问题,以及由此产生的关于TA的歧义 getRole() method:

(Incidentally, 注意上面继承图的菱形, 这就是为什么这被称为“钻石问题”.)

Which getRole() 实现应该继承TA? 教员或研究生的证言? 简单的答案可能是让TA类覆盖 getRole() 方法并返回名为“TA”的新定义角色。. 但这个答案也是不完美的,因为它会掩盖一个事实,即助教是, in fact, 既是教员也是研究生. 有多种设计方法和模式可以在没有多重继承的情况下处理这种类型的情况, 这就是为什么一些语言(Java就是其中之一)决定简单地避开多重继承的原因.

Java 8, however, 通过允许在接口上指定默认方法(在Java 8之前),引入了对多重继承的准支持形式, 只有方法签名, 不是方法定义, 允许在接口上使用). Since Java does 允许单个类实现多个接口(而单个类只能扩展单个父类), Java 8中允许在接口中定义方法,这首次在Java中引入了菱形问题的可能性.

For example, if A, B, 和C是接口, B和C可以各自为a的抽象方法提供不同的实现, 导致任何实现B和C的类D出现菱形问题. 类D必须重新实现该方法(其主体可以简单地将调用转发给其中一个超级实现), 否则歧义将作为编译错误而被拒绝.

Gourmet Java

在这里,我们将介绍一些更高级的概念和问题,Java编程大师可能会熟悉这些概念和问题.

问:如何使用外部条件变量可靠地退出线程?

有时,开发人员希望在外部条件为真时终止线程. 考虑下面的例子 bus 继续无限驱动的线程,直到 pleaseStop 变量变为真.

boolean pleaseStop = false; // The bus pull cord.

公共void pleaseStopTheBus() {
    pleaseStop = true;
}

公共无效startTheBus() {
    new Thread("bus") {
        公共无效运行(){
            //无限驱动总线.
            while (!pleaseStop) {
                //花点时间开车到下一站.
            }
            pleaseStop = false; // Reset pull cord.
        }
    }.start();
}

看起来简单. However, Java不保证线程边界之间隐式的变量同步, 所以这个线程不能保证可靠地退出, 这让缺乏经验的Java开发人员感到头疼.

要使上述代码正常工作,需要按以下方式同步线程:

volatile boolean pleaseStop = false; // The bus pull cord.
Object driver = new Object(); // We can synchronize on any Java object.

公共void pleaseStopTheBus() {
	//在"线程1"中,同步驱动程序对象
    Synchronized (driver) {
        pleaseStop = true;
    }
}

公共无效startTheBus() {
    new Thread("bus") {
        公共无效运行(){
            //无限驱动总线.
            while (true) {
				//在这里的“线程2”,也同步驱动程序对象
                Synchronized (driver) {
                    if (pleaseStop) {
                        pleaseStop = false; // Reset pull cord.
                        return; // Bus stopped.
                    }
                }
                //花点时间开车到下一站.
            }
        }
    }.start();
}

Q: How can null 问题重重,怎样才能避免陷阱?

For one thing, null is often ambiguous. 它可以用来表示成功或失败. 或者它可以用来表示值的缺失. 或者在某些上下文中它可能是一个有效值.

即使一个人知道 null 在特定的环境中, 如果不幸的开发人员在取消引用它之前忘记检查它,它仍然会造成麻烦, 从而触发 NullPointerException.

避免这些问题的最常见和最有效的技术之一是 使用有意义的非空默认值. 换句话说,就是避免使用 null 尽你所能. 避免将变量设置为 null 避免返回 null 从任何可能的方法(例如.g.,返回空列表,而不是 null).

In addition, as of JDK 8, Java已经引入了对 Optional 类(或者如果您使用的是较早版本的Java,则可以使用 Optional class in the Guava libraries. Optional 用一个值表示和包装缺席和存在. 而Optional则添加了更多内容 ceremony 到您的代码中,通过强制您展开 Optional 得到非-null 值,它避免了可能导致的 NullPointerException.

问:什么是“拳击”?要注意的问题有哪些?

Java的基本类型是 long, int, short, float, double, char, byte and boolean. 通常需要将原始值作为对象存储在各种数据结构中,这些数据结构只接受诸如 ArrayList, HashMap, etc. 因此,Java引入了“装箱”的概念,将原语打包成对象类的等效物, e.g., Integer for int, Float for float, and Boolean for boolean. Of course, as objects, 它们会导致对象分配的开销, 内存膨胀和方法调用, 但他们确实付出了一些代价来达到目的.

“自动装箱”是编译器自动将原语转换为装箱对象,反之亦然. 这只是为了方便,e.g.:

ArrayList ints = new ArrayList();

// Autoboxing.  编译器会自动将"35"转换成一个带框的整数.
ints.add(35); 

//上面的表达式等价于:int.(新添加整数(35));

尽管它们很方便, though, 盒装对象因引入粗糙的bug而臭名昭著, 特别是对于经验不足的Java开发人员.

首先,想想这个:

System.out.println(new Integer(5) == new Integer(5));   // false

在上面的代码行中,我们比较了 identity 两个整数对象. Since each new Integer(5) 创建一个新对象 new Integer(5) 不等于另一个 new Integer(5).

但更令人不安的是下面这个看似莫名其妙的区别:

System.out.println(Integer.valueOf(127) == Integer.valueOf(127));   // true
System.out.println(Integer.valueOf(128) == Integer.valueOf(128));   // false

Huh? 这怎么可能呢 true and the other be false? 这似乎说不通啊. 事实上,答案非常微妙.

正如在一个容易被忽视的 note 在Javadoc中 Integer class, the valueOf() method method缓存取值范围为-128到127的整数对象, inclusive, 也可能缓存这个范围之外的其他值. 因此,调用一次返回的Integer对象 Integer.valueOf(127) will 方法返回的Integer对象 Integer.valueOf(127),因为它是缓存的. 但在-128到127的范围之外, Integer.valueOf() calls, 即使是相同的值, 不一定会返回相同的Integer对象(因为它们不一定被缓存).

同样重要的是要注意,使用盒装对象的计算时间可能是使用原语的6倍左右, 以下基准测试代码可以证明这一点:

void sum() {
	Long sum = 0L; // Swap "Long" for "long" and speed dramatically improves.
	for (long i = 0; i <= Integer.MAX_VALUE; i++) {
		sum += i;
	}
}

执行上面的代码 sum declared as Long 花费6547ms,而相同的代码使用 sum declared as long (i.e.(原始类型)只花了1138ms.

问:什么是类型擦除?

向语言中添加泛型并非没有问题. Java泛型的一个特别棘手的问题是 type erasure.

作为一个例子,考虑以下代码片段:

List a = new ArrayList();
List b = new ArrayList();
return a.getClass() == b.getClass();  // returns true??!!

这应该会返回 false since a and b 不同的类类型(i.e., ArrayList vs. ArrayList), yet it returns true. Why?

这里的罪魁祸首是类型擦除. 一旦上面的代码通过了所有的Java编译器验证,编译器 erases the String and Integer 类型,以保持与旧jdk的向后兼容性. 因此,上面的代码被Java编译器转换为以下代码:

列表a = new ArrayList();
List b = new ArrayList();
return a.getClass() == b.getClass();  // returns true (understandably)

因此,在编译后的代码中, a and b 都是没有类型的吗 ArrayList 对象,而其中一个是 ArrayList 另一个是 ArrayList is lost. 尽管在实践中,与类型擦除相关的问题很少给开发人员带来问题, 这是一个需要注意的重要问题,在某些情况下可能会导致非常严重的bug.

问:请描述一下观察者模式以及如何在Java中使用它. 提供一个示例.

The Observer pattern 让对象注册,以便在观察对象发生变化时接收其发出的通知. 的内置支持 Observable class and Observer interface.

下面是一个实现Observable的简单例子:

公开类展览主义者{
	MyObservable = new MyObservable();

	公开展示者(){}

	public java.util.getObservable() {
		返回myObservable;
	}

	private void触发器(字符串条件){
		myObservable.invalidate();
		myObservable.notifyObservers(条件);
	}

	私有类MyObservable扩展java.util.Observable {
		Private void invalidate() {
			setChanged();
		}
	}
}

下面是一个相应的Observer示例:

public类Voyeur实现Observer {

	公众偷窥狂(暴露狂){
		//注册为对“暴露狂”感兴趣.
		exhibitionist.getObservable().addObserver(this);
	}
	
	@Override
	public void update(Observable o, Object arg) {
		//当observable通知它的观察者时调用.
		System.out.println(arg.toString());
	}
}

使用这种方法也有一些缺点:

  1. 观察到的类必须扩展 Observable 从而阻止它扩展一个更理想的类(请参阅我们前面关于 多重继承)
  2. 被观察类和观察类是紧密耦合的,可能导致 NullPointerException如果你不小心的话.

为了避免第一个问题,高级开发人员可以使用代理(委托) Observable 对象,而不是扩展它. 要解决第二个问题,可以使用松耦合的发布-订阅模式. 例如,您可以使用Google的Guava Library EventBus 对象连接到中间人的系统.

问:描述一下Java中的强引用、软引用和弱引用. 何时、为何以及如何使用它们?

在Java中,当分配一个新对象并将其引用(简单的指针)赋值给一个变量时,a strong reference is created by default; e.g.:

String name = new String(); // Strong reference

然而,Java中还有两个额外的引用优势可以显式指定: SoftReference and WeakReference. (实际上在Java中还有一种额外的引用强度,称为 PhantomReference. 这是很少使用的, though, 即使是经验丰富的Java开发人员也很可能不熟悉它, 所以我们从这里的讨论中省略了它.)

为什么需要软引用和弱引用,它们什么时候有用?

Java的垃圾收集器(GC)是一个后台进程,它定期运行以从应用程序的内存堆中释放“死”对象(没有强引用的对象). 尽管GC有时给人的印象是一个神奇的黑盒, 它其实并没有那么神奇. 有时你必须帮助它,以防止内存被填满.

More specifically, GC不会从强引用对象链中释放可强访问的对象. 这句话的意思就是, 如果GC仍然认为需要某个对象, it leaves it alone, 这通常是你想要的(i.e.(你不希望一个你需要的对象在GC启动时突然消失).

但有时强引用太过强大,这时软引用和弱引用就派上了用场. Specifically:

  • SoftReference 对象根据内存需求由垃圾收集器自行清除. 软引用最常用于实现对内存敏感的缓存.
  • WeakReference 对象不会阻止它们的引用对象被设置为可终结的、被终结的,然后被回收. 弱引用最常用于实现规范化映射.

Wrap up

Java作为一种占主导地位的流行语言继续生存和发展. 但是正如在软件开发中的任何语言所期望的那样, Web和移动应用开发经历了多次迭代, 它有许多并非所有开发人员都熟悉的细微差别. Moreover, Java功能不断增长的广度需要大量的经验才能完全理解. 因此,那些掌握了该语言的人可以对开发团队的生产力和系统的性能产生重大的积极影响, scalability, and stability.

本文提出的问题和技巧对于识别真正的Java大师可能是有价值的辅助工具. 我们希望您发现它们是在寻找高级Java开发人员中的少数精英时“去粗取精”的有用基础. 然而,重要的是要记住,当您寻求雇用Java程序员时,这些工具仅仅是作为将其纳入整体招聘工具箱和策略的更大上下文中的工具.

(最后一点:如果你对Java感兴趣的是android手机应用, 我们建议您阅读我们的 Android面试内幕指南 as well.)

顶级Java开发人员需求量很大.

Start Hiring