每个优秀的Java / Java EE开发人员都应该回答的问题吗?[关闭]


138

我正在研究每一个好的.Net开发人员应该能够回答的问题,并且对该问题的内容和方法印象深刻,因此,本着同样的精神,我正在向Java / Java EE开发人员提出这个问题。

有什么问题你认为应在良好的Java / Java EE的程序员能够回答?

我将此问题标记为社区Wiki,因为它不是特定于用户的,并且旨在为整个编程社区提供服务。

期待一些惊人的回应。

编辑:也请按照评论中的建议回答问题,以便人们也可以学习有关该语言的新知识。


3
为什么这个问题无法与.Net问题得到类似的答复?
Rachel 2010年

5
善良的主:) ,. Net问题是一年前提出的,这个问题只有一天的历史,您正在比较答案。
轰击

1
您为什么不编辑问题并添加句子“请回答您自己的问题。”,以便人们甚至可以学到一些东西(新知识)。
r3zn1k 2010年

9
“企业版的当前缩写是什么?”;)
Bozho 2010年

17
阿尔伯特·爱因斯坦的轶事。爱因斯坦的一位同事有一天向他询问他的电话号码。爱因斯坦伸手去找电话簿,然后查了一下。“你不记得自己的电话号码了吗?” 男人问,吓了一跳。“不,”爱因斯坦回答。“为什么我要记住可以轻易从书中得到的东西?” 我能到达所有人吗?)?是的,我知道,爱因斯坦没有面对面试官……
SB。

Answers:



70

Set,Map和List有什么区别?

我仍然感到惊讶的是,有多少人在电话采访中不认识这一个人。


8
当然,但是在网上查看文档(“ java集合框架”)大约需要20秒钟,因此,许多有价值的人可能不会费心将其保存在内存中。
Manur 2010年

127
不,对不起,不要买,这是每个开发人员都应该知道的基本知识。
乔恩

15
我要说的是,甚至想到软件工作的任何人都不仅需要理解这一点,还需要理解不同种类的列表(ArrayList / LinkedList)之间的差异。不一定是最佳实现,甚至不是O(n)表示法,而是对何时使用什么内容的正确理解。
贡佐牧师

11
+1 @Jon:我通常赞成“无需记住细节”的观点,但是,如果您甚至不了解这些基本接口之间的基本概念差异,那么您绝对不是一个好的Java开发人员。
约阿希姆·绍尔

13
@Joachim:您可以在语句中删除“ Java”一词。集,映射和列表是基本的算法概念。
CPerkins 2010年

44

一个接口可以扩展多个接口吗?

大多数人回答“否”,因为他们知道Java没有多重继承。但是一个接口仍然可以扩展多个接口(但是一个类不能扩展多个类)。这不会导致钻石问题。

如果答案是“否”,面试官要问“为什么是被禁止?”。然后您开始考虑它,您应该意识到它没有问题。

因此,您在面试中(自己)学到了一些东西,并向面试官展示了您能够推理类,对象,继承,多态性等方面的知识。实际上,这比一个心地知道答案但不知道答案的候选人要好得多。明白为什么


昨天我将C ++讲师与钻石继承问题混淆了,她一点都不知道:)
Esko 2010年

2
曾经有人问我这个问题,我回答“否”。我认为这是压力,我回答得太快了。对于您从未使用过的事物,总是很难知道答案。
IAdapter 2010年

1
我将在本文中详细说明。回答“否”实际上是可以的。这个问题的好处是,这是引发关于OO概念的讨论并了解候选人原因的好方法。如果您只是想让面试官听到“是”,那就毫无意义。实际上,接口的多重继承并不是众所周知的。
ewernli 2010年

3
这个问题的棘手版本是“ java是否支持多重继承?” 答案仅是针对接口的“排序”
nsfyn55 2011年

23

在方法调用中使用final关键字。例如,为什么尽管在方法参数中使用了最终限定符,但下面的代码中的方法测试为什么没有给出任何编译错误。

class Name {
    private String name;

    public Name (String s) {
        this.name = s;
    }

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

private void test (final Name n) {
    n.setName("test");
}


我真的很想知道这个问题的答案。听起来很有趣。
雷切尔

@Rachel:原因是因为final关键字应用于Name对象,而不是name类的字段Name
ryanprayogo,2010年

20
好吧,该参数n被声明为final,这意味着它不能在test方法主体中重新分配。它不会导致错误,因为该方法test不会尝试重新分配参数,它只是在参数上设置属性... n = new Name("test");会导致编译错误...
rjohnston 2010年

7
添加到@rjohnston的注释中:使用final for方法参数不能确保类实例的不变性。如果需要不变性,则应该设计类(在当前情况下为Name)(例如,在当前情况下不提供设置者)
sateesh 2010年

谢谢大家分享宝贵的信息。非常感谢您对此的投入。
雷切尔

19

一种确定是比较字符串。之间的区别

字符串helloWorld =“ Hello World”;
helloWorld ==“ Hello World”;
“ Hello World” .equals(helloWorld);


14
相当确定,您需要执行类似new String(“ Hello World”)的操作。是不是从池中提取了字符串常量,就像intern()会产生的效果一样,因此使这两个语句都成立了吗?
史蒂文·斯兰斯克


17

技巧问题:Java中通过引用传递了哪些参数?

令人惊讶的是,还有多少人仍然模仿“基元通过值传递,对象通过引用传递”的口头禅。


4
我想知道正确的答案是否始终是面试中给出的答案。在我面试过的地方,面试官也模仿了同一件事。
MAK 2010年

2
我注意到在回答有关Java的问题时,将C作为第一语言学习的人们与将C ++作为第一语言学习的人们之间存在差异。可能是因为C用户被告知传递指向值的指针是“按引用传递”。
乌里(Uri)2010年

23
这是一个愚蠢的问题,因为如果您还问“引用带来的后果是什么?”,那么“错误”的答案很可能在技术上正确。这只是定义引用传递的方式,因此在Java世界中没有太大价值,因为只有一种传递对象的方法。了解实际发生的情况比使用任意定义以所需方式通过引用传递更为重要。
x4u 2010年

3
这个问题至少是有问题的,因为它主要取决于“按值传递” /“按引用传递”的准确定义,而该定义经常被错误地使用。尽管我同意优秀的开发人员应该了解这些定义,但了解其后果更为重要。如果您了解Java的实际行为,那么知道该概念的正确名称并不是很有意义,因为在实践中这不是您要讨论的内容,因为它永远不会改变。
sleske

3
嗯,对象通过Java引用传递的。您不能按值传递对象;除其他事项外,对象永远不会存在于堆栈中。当然,引用是按值传递的。
肖恩·欧文

17

您说“好”,“开发人员”。这也是我的2美分.. :)

  • “受检查的异常”是什么意思?
  • 哪种方法更好,何时使用:断言或异常以处理意外情况?
  • 为什么String类是最终的?(或者不是吗?;))
  • 类中的wait,notify和notifyAll方法是什么?
  • 为什么Thread类不是final?为什么要扩展Thread?
  • 为什么有两个Date类;为什么?一个在java.util包中,另一个在java.sql中?
  • 如果在finally块中引发异常,会发生什么情况?其余的是否最终执行?
  • 可以使用垃圾收集器,但是Java应用程序中是否完全没有内存泄漏?如果没有,怎么办?

对于J2EE:

  • 在Servlet中包含实例/静态变量是否很好?为什么不?那你在哪里存储“状态”?
  • 继续上述问题:(网络)应用程序的“状态”在哪里?
  • 如果我开始在“ JSP”中创建/关闭数据库连接会怎样?
  • 处理JSP异常的方法是什么?试着抓?嗯..还有其他吗?

我可以想到还有很多很多其他功能,但现在就可以了:)


8
答案会很好,我不知道其中的一些答案。
MAK 2010年

受检查的异常是程序必须制定计划以应对的异常。如果在引发已检查异常的内容周围没有try / catch块,则程序将无法编译。wait,notify和notifyAll用于同步线程,并且在Java中可以同步所有对象。如果从概念上讲,类需要自己的线程,则我将扩展Thread(而不是实现Runnable),即该类需要进行一些管理,并且不代表可以在另一个工作线程上运行的任务。
ZoFreX

如果在finally块中引发了异常,则其余部分将不会运行。在“纯” Java程序中,不存在规范的内存泄漏。但是,如果数据结构包含对不再需要的对象的引用,则仍然可以使用不应该使用的内存。如果使用本机库,则可能需要管理其资源,例如在SWT中,对某些资产调用.dispose()以确保它们不会泄漏很重要。
ZoFreX

2
将断言用于“将永远不会发生”的错误,这些错误将在开发中处理。将异常用于可能在运行时实际发生的错误,程序将需要以某种方式处理它们。
MatrixFrog 2011年

16

String,StringBuffer和StringBuilder有什么区别?


5
String-表示字符串的不可变类。StringBuffer-Java的较早版本中引入的构建器模式,该模式在每个操作(或大多数操作)上同步以用于构建String。StringBuilder-在Java 5(JDK 1.5)中引入的一个类,该类共享StringBuffer API,用于构建不对每个操作(或大多数操作)进行同步的String 。因为String的构造倾向于在单个线程中发生,所以StringBuilder在支持它的Java运行时/ JDK中是首选。
MetroidFan2002 2011年

13

“什么是部署描述符?”

如果候选人不由自主地发抖,那么他就有使用3.0之前的EJB的经验。


使其成为“不由自主​​地颤抖+大汗淋漓+在重复此问题2次后就掉了下去”,我有时会觉得这是他们添加/支持整个Annotations的“唯一原因”!:)
Elister

12

许多问题和访谈都可以在http://www.techinterviews.com/interview-questions/java上获得,我真的不认为复制/粘贴其中的内容会有价值。

不,这是你来创建你自己的东西编译认为是很重要的。就我个人而言,我总是分两个步骤进行:首先是几个问题,以获取有关经验和技能的基本概念,然后是解决问题的情况。我确实不相信能够回答任何已知问题会使您成为好问题或不好的未知问题解决者。因此,我更愿意要求人们解决给定的问题,给他们一些要求,并要求他们编写代码(但不是在纸上)。我给他们一些时间来找我,检查他们是如何做到的,他们的编码风格,他们如何使用建议的API等。

综上所述,我最喜欢的问题是“您不喜欢Java什么?” (本着这个精神)。这确实是一个很好的问题,它为您提供了有关候选人使用Java并探索其API的程度以及他是否只是出于宗教信仰的即时反馈(如OP所写)。

更新:正如CPerkins所建议的那样,上面建议的问题的措辞更好的措词可能是“您最想看到Java发生了什么变化?”。确实,我更喜欢这种方式。


我不喜欢“您不喜欢Java吗?”这个问题,我会撒谎,因为听起来就像“您为什么离开上一家公司?”。加上他们可能会想-“如果您讨厌Java,我们将不会为您提供工作”。
IAdapter 2010年

@ 01是您的权利,但我不同意您的意见,我认为您没有提出这个问题。
Pascal Thivent 2010年

1
我通常看到的内容更像是:“您最想看到Java中的更改是什么”,而不是“不喜欢”。
CPerkins 2010年

@CPerkins实际上,这是一个更好的措辞,比“不喜欢”好,比“恨”好(在参考文献中)。谢谢。
Pascal Thivent 2010年

11

什么是System.out.println中的'System','out','println'?当您在HashMap上调用“放置”时会发生什么?


答案是什么?我从来没有想过什么系统类!我想知道知道的是:)
palAlaa

10
  1. 解释Java中使用的各种访问修饰符。我有很多人为此感到困扰,尤其是默认访问权限。
  2. 如果您可以更改有关Java语言或平台的一件事,那将是什么?优秀的开发人员将在这里给出答案,而对开发不真正感兴趣的人可能不在乎。
  3. 如果他们的简历说类似他们使用EJB2.1,那么请询问EJB3以了解他们对此有什么了解。最好的开发人员即使不使用较新的版本,也会跟上最新的发展。

3
如果只是有一个事情我可以改变,我想补充运算符重载的语言,很可能只是一个受限制的重载操作(即没有超载new^>><<>>>)。如果我可以更改另一件事,那就是添加真正的按引用调用语义。第三件事是添加unsigned整数类型。
2010年

1
委托和闭包,也许是lambda表达式,但这并不是必须的。扩展方法也会很出色。如果使用得当,它们确实可以清除代码。
乔尔

10
  • 压倒一切等于什么时的总合同是什么?
  • 更好的选择更喜欢列表或数组吗?
  • 普遍接受的命名约定是什么?
  • 序列化如何工作?
  • 如何实现可比性?
  • 使用JDBC的Prepared语句有什么优势?
  • 什么是Java EE?
  • 什么是容器及其提供的服务?

9

如果您正在使用Java的“经验”来招聘毕业生,那么像编写一些将导致引发NullPointerException的代码这样的简单问题可以区分哪些候选人最近使用过Java,而不仅仅是在完成单元/课程时就停止了学习。


16
“抛出新的NullPointerException()”是否正确?
托尔比约恩Ravn的安德森

1
好吧,这取决于面试官。如果他们展示了一个测试变量并抛出NPE并提供有用信息的示例,那么我会很高兴。如果我认为他们使用该答案是因为他们无法提出一些合法抛出NPE的代码,那么我会担心。
戴维(David)2010年

9

将打印什么?

public void testFinally(){
    System.out.println(setOne().toString());

}

protected StringBuilder setOne(){
    StringBuilder builder=new StringBuilder();
    try{
        builder.append("Cool");
        return builder.append("Return");
    }finally{
        builder.append("+1");
    }
}

回答:CoolReturn + 1

更加困难:

public void testFinally(){
    System.out.println(setOne().toString());

}

protected StringBuilder setOne(){
    StringBuilder builder=new StringBuilder();
    try{
        builder.append("Cool");
        return builder.append("Return");
    }finally{
        builder=null;  /* ;) */
    }
}

:CoolReturn


第一个代码指示即使在try块中可以使用return语句,最后总是会被执行,但是我没有第二个代码?语句builder = null时发生了什么;发生??
palAlaa

3
@Alaa,这几乎就像为构建器设置了一个临时值,在finally块中将构建器设置为null,然后返回了临时值。
威慑

1
@VextoR,是的,Alaa给出了很好的描述。该代码检查被访者如何理解尝试...最终阻止了内部返回,并且变量的作用域通常为变量处理
zaletniy 2011年

4
return语句返回对StringBuilder对象的引用。最终更改引用不会对实际返回的引用产生任何影响。但是,如第一个示例所示,更改对象的内容确实会影响返回的内容
Derek Litz

8

抽象类和接口之间有什么区别?您什么时候会使用它们?

许多Java开发人员都不知道这一点,我在大学的计算机科学课程中问过大多数人,而绝大多数人都无法回答。


唯一的区别是抽象类可以包含非抽象方法。
TBH

1
当然,如果您读了一本Java书籍,那么这就是答案。虽然那时您可能还补充说它们也可以包含成员变量:P但是,何时使用它们以及为什么使用它们的区别更加有趣。
ZoFreX

1
接口的使用为我提供了非常强大的技术,即多态性,它可以从实现该接口的类中调用任何重写的方法,从而使您无需了解每个子类的类型。
palAlaa

@TBH-不要忘记,在Java当前使用的单一继承模型中,您只能为一组功能扩展一个抽象类-但是您可以在一个类中组合多个接口以实现无需单一功能即可实现的多个功能继承限制。
MetroidFan2002 2011年

8

简单的问题,例如,

  • 什么是JRE和JDK?
  • 为什么Java要求互操作性?

尽管这些是非常基础的,但许多开发人员都不知道答案。我建议在与代码相关的查询之前询问这些问题。


不了解JDK / JRE部分。例如,在Mac上没有这种区别。因此,作为Mac上的Java开发人员,实际上根本不需要了解这一点。
Fabian Steeg,2010年

我认为这是一个很好的问题,它是否有助于揭露那些被误导以至于无法尝试在Mac上进行认真的Java开发的人们。严重的是,如果您声称自己是Java开发人员,但不知道该单击哪个下载链接来单击java.sun.com,则存在问题。
Mark B 2010年

作为一名Java开发人员,完全不必担心他/她所使用的平台。了解Java工具似乎是基本要求。至少我这么认为。关于我在其中工作的操作系统。
拉维沙(Ravisha)2010年

@mbaird这是一个相当卑鄙的评论。尽管我在Mac上进行开发并且确实知道JRE / JDK是什么,但老实说,在实际开发中,这真的很重要吗?特别是对于使命令行使用成为过去的IDE,Java开发人员比其他任何人都需要更多地了解如何使用该语言。
亚历克西斯·金

6

前5个J2EE / JEE问题

我遇到的J2EE / JEE中间件问题列表非常长,但是以下是我被问到的前5个问题,并引起了很好的讨论:

  1. 当MDB遇到无法处理的异常时会发生什么?
    这个问题通常会引发有关毒药消息,错误队列等的各种有趣的讨论,
  2. 给定一个JMS主题,并有几个使用不同JVM的使用者,在有或没有耐用使用者的情况下,对各种方案都存在疑问。
    这个问题通常可以让我讨论何时使用持久订阅者,何时使用队列等。
  3. 如果在访问Hibernate / JPA POJO内容导致异常的情况下陷入困境,该如何解决?
    这导致了关于延迟加载,补液等的精彩讨论,甚至导致JPA与Entity bean的比较和对比。我发现进行准备并弄清楚概念很有用。
  4. 如何提供简单的Web服务?
    从简单的基于Web服务器的解决方案到复杂的SOAP / REST解决方案,以及两者之间的任何解决方案,都应该足够好。另外,根据访问者的观点,有时它会引发一些有趣的话题,例如一些设计思想,例如WSDL,文档样式,SOAP中介等等。这些问题可能会引起诸如在JAX-WS上比JAX进行改进的问题。 -RPC或基于SOAP1.1的SOAP1.2,答案通常取决于我记得多少。
  5. JEE 5资源注入
    服务定位器模式到javax.naming.Context问题,提出问题的方式很多。

我发现另一个令人费解的棘手问题,但遇到了很多次,那就是, 依赖库如何打包到存档中?
捆绑归档中各个类的可见性。
如果讨论没有导致不同应用程序服务器,资源档案库等的类加载器层次结构,那么最好辞职并继续。

Java的5大核心问题:

  1. 关于java.util.collections的问题
    这是所有问题的源头。一旦您可以有效使面试官进入该区域,并且如果您准备好了,其余的面试通常会留在这里。可以肯定的知道SetListMap,和的重要性Object.equals(),并Object.hashCode()在这些接口的每个实施。
  2. 重构问题
    如果面试官有开放的态度,那么这些问题就很好。如果面试官已经有了特定的解决方案,而您的面试官与他/她不匹配,那么您注定要失败。最好同意以下答案:“我知道其他解决方案也是可能的。”
  3. 与早期JDK版本相比,关于JDK5中的多线程问题, 我发现最好使用java.util.concurrent包类进行准备。道格·李(Doug Lea)的书提供了大多数答案。
  4. JDK1.6 / JDK1.7中有什么新功能...?
    这是许多面试官肯定会提出的问题。尽管我讨厌这个,但最好做好准备。至少记住我曾与之合作过的一些内容,并引导讨论朝着其他方向发展,从而在很大程度上有效地躲避和解决了问题。
  5. Java API中的模式
    一次又一次,我被要求指出Java API中的GoF模式。最好为此做好准备。




4

一个更纯净的Java问题:

睡眠和等待之间有什么区别?实际上,没有多少人知道等待的方式。

您需要如何处理InterruptedExceptions?


4

这是我在面试中遇到的问题。

为什么在Java中将main方法称为public static void main(String [] args)?

回答:

1. main()必须声明为public,因为只要程序开始执行,JVM就会调用main()。JVM不属于我们的程序包。

为了访问包外部的main,我们必须将其声明为public。如果我们声明为public以外的任何其他东西,则它会显示运行时错误而不是编译时间错误

2. main()必须声明为静态的,因为如果方法被声明为静态的,那么我们可以使用ClassName.methodName()在类之外调用该方法

class Sample
{
     static void fun()
     {
           System.out.println("Hello");       
     }
}

class Test
{
      public static void main(String[] args)
      {
                Sample.fun();
      }
}

JVM首先将加载Test类,并将检查Commandline参数并将主方法调用为Test.main();。

3. main()必须声明为void main(),因为JVM不会期望main()提供任何值。因此,必须将其声明为void。

如果提供其他返回类型,则为RunTimeError,即; NoSuchMethodFoundError。

4. main()必须将String参数作为数组,因为JVM通过传递命令行参数来调用main方法。由于它们存储在字符串数组对象中,因此作为参数传递给main()。


public static void main(String... args)如果您倾向的话可以使用:-)它的签名与[]
corsiKa 2011年

3

J2SE和J2EE(或JSE和JEE)之间有什么区别?

开发人员应该能够指出,企业版基本上是可以由供应商实施的接口定义(即规范)。标准版本身就是一个实现


4
在一天结束时,保持营销术语统一的能力真的那么重要吗?
劳伦斯·贡萨尔维斯

@劳伦斯-这是荒谬的话。两者之间确实存在差异,您会惊讶有那么多所谓的经验丰富的开发人员根本不理解
oxbow_lakes 2010年

我的观点是,如果某人是一个优秀的编码人员,那么他们如果知道J2SE和J2EE之间的区别,我就不会在乎。
劳伦斯·贡萨尔维斯

我将问题理解为“ JEE + JSE开发人员应该知道的东西”,在这种情况下,我认为了解两种技术之间的差异是相关的。
oxbow_lakes

4
@ThorbjørnRavn Andersen我怀疑大多数Java编码器(包括优秀的编码器)是否强烈意识到上述区别,“企业版基本上是接口定义,而标准版本身就是一种实现”。对于大多数优秀的Java程序员而言,重要的区别是哪些API可用。例如:Servlet是EE等的一部分。无论如何,正如我认为找到优秀的程序员比优秀的Language-X程序员更重要一样,我认为找到优秀的Java程序员比优秀的JSE / JEE程序员更重要。
劳伦斯·贡萨尔维斯


2

关于什么是会话bean,并描述无状态会话bean和有状态会话bean之间的一些区别。


2

编写一个程序以接受两个整数并将两个数字中的最大值输出到您选择的位置的文件中。现在描述每个语句的作用。

从import语句的重要性开始,甚至深入到异常终止,都有可能深入挖掘


2

核心:1.什么是检查异常和未检查异常?2.在代码中添加新异常时,何时使用哪种类型(已检查/未检查)?

Servlet:1. response.sendRedirect()和request.forward()有什么区别?


您能回答这些问题吗?这是我第一次了解“已检查和未检查的异常”!
palAlaa

简单的谷歌搜索可以引导你答案:google.co.in/...
郁慕明

1

threads工作如何?什么synchronized啊 如果synchronized一个类中有两个方法,它们可以同时由两个线程执行。听到很多人回答是,您会感到惊讶。然后是所有与线程相关的问题,例如死锁饥饿等。


2
那是因为答案“是” ...
Fortega 2010年

@Fortega-怎么可能?每个方法在对象上都有一个锁。如果thread正在运行该方法,则其他任何人thread都无法获得该锁。
fastcodejava

1
如果您有两个相同类型的对象,则可以同时在第一个对象上调用第一个方法,并在第二个对象上同时调用第二个方法。当然,除非方法是静态的。
Fortega

2
如果您不正确地了解锁定的发生方式,那并不是没有道理。同样,尽管这可能是一个明智的选择,但这并不意味着我的回答是不正确的:-)
Fortega 2010年

1
答案可能会让没有在工作中使用线程的程序员感到困惑,但我认为这是一个好方法:)
palAlaa 2010年

1

许多Java程序员不知道的一件事是字符串是不可变的,因此请使用StringBuilder或StringBuffer!

String s = "";
for(int i = 0; i < 100; i++) {
  s += "Strings " + "are " + "immutable, " + " so use StringBuilder/StringBuffer to reduce memory footprint";
}

以及数字,例如整数,长整数等
亚瑟罗纳德2010年

在性能方面,串联不可变字符串和使用StringBuilder之间不再存在区别。这是因为现代的Java编译器将优化连接: java.sun.com/docs/books/jls/third_edition/html / ...最好使用更易读的方法。
布伦特·威尔逊

1
@BrentWilson所链接的内容不会按照您的想法进行。它将s += "a" + "b" + "c"变成一个Stringbuilder.append(...)场景。但是它不会优化for循环。此答案中的代码最终将char[]在这些StringBuilder中创建总共201个String,100个StringBuilder,以及(取决于实现)300个不同的s,并估计包含425k +个字符。完全将其更改为使用StringBuilder会将其减少为1个String,1个StringBuilder和13-15个内部char[]s ,而仅使用〜8k个字符,而不是应该的。
corsiKa 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.