Java基础面试题:语法


1. 面向对象的三大特性

封装

每个对象包含它能进行操作所需要的所有信息,这个特性称为封装,因此对象不必依赖其他对象来进行自己的操作。将方法、属性、字段包装在类中,通过实例化类来生成对象。

封装就像建房子,类就是房子,属性是门窗,字段是房子里的东西,方法是人的行为。属性对字段有保护作用,防止字段被随意的修改或读取。

  • 好的封装能减少耦合
  • 类内部的实现可以自由修改
  • 类具有清晰的对外接口

继承

继承代表一种is-a关系(子类is父类),是面向对象程序设计能够提高软件开发效率的重要原因之一。子类具有(继承)父类的所有特性,也可以定义自己独有的特性。

  • 子类无法直接访问父类的private的属性和方法
  • 子类可以扩展父类没有的属性和方法
  • 子类可以重写父类的方法
  • 继承是具有传递性的
  • 继承来的属性和方法是隐式的
  • 缺点:子类和父类具有强耦合性

多态

多态表示不同的对象可以执行相同的动作,但要通过他们自己的实现代码来执行。比如猫和狗继承自动物,猫叫和狗叫都是相同的动作-动物叫,但是实现方式不同。

  • 子类可以以父类的身份出现 (使用父类对象的地方都可以用子类来代替)
  • 子类在工作时以自己的方式来实现
  • 子类以父类的身份出现时,子类特有的方法和属性不能使用
  • 多态的作用是消除类型之间的耦合关系

多态就是对象拥有多种形态:引用多态和方法多态

  • 引用多态:父类的引用可以指向本类对象、父类的引用可以指向子类的对象
  • 方法多态:创建本类对象时,调用的方法为本类的方法;创建子类对象时,调用的方法为子类重写的方法或者继承的方法

存在多态的必要条件:继承、重写、向上转型

  • 继承:在多态中必须存在有继承关系的子类和父类。
  • 重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
  • 向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。

只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。

对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。

在Java中有两种形式可以实现多态。继承和接口

基于继承的实现机制主要表现在父类和继承该父类的一个或多个子类对某些方法的重写,多个子类对同一方法的重写可以表现出不同的行为。

在接口的多态中,指向接口的引用必须是指定这实现了该接口的一个类的实例程序,在运行时,根据对象引用的实际类型来执行对应的方法。

继承都是单继承,只能为一组相关的类提供一致的服务接口。但是接口可以是多继承多实现,它能够利用一组相关或者不相关的接口进行组合与扩充,能够对外提供一致的服务接口。所以它相对于继承来说有更好的灵活性。

2. 面向对象的四大特征

抽象

抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。

继承

继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。

封装

封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。

多态性

多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。

3. 语句float f=3.4是否正确

不正确,编译不能通过;精度不准确,应该用强制类型转换。

如下所示:

float f=(float)3.4;

4. 语句short s1 = 1; s1 = s1 + 1;是否正确

short s1 = 1; 
s1 = s1 + 1;

s1+1运算结果是int型,需要强制转换类型。

short s1 = 1; 
s1 += 1;

可以正确编译,自动类型提升。

5. Java有没有goto

goto 是java 中的保留字,现在没有在java 中使用。

6. int和Integer有什么区别

Java 提供两种不同的类型:引用类型和原始类型(或内置类型);

int 是Java的原始数据类型,Integer 是Java为int提供的封装类。

Java 为每个原始类型提供了封装类:

原始类型 封装类型
boolean Boolean
char Character
byte Byte
short Short
int Integer
long Long
float Float
double Double

引用类型和原始类型的行为完全不同,并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为null,而原始类型实例变量的缺省值与它们的类型有关。

7. 逻辑操作(&,|,^)与条件操作(&&,||)的区别

区别主要有两点:

  • 条件操作只能操作布尔型的,而逻辑操作不仅可以操作布尔型,而且可以操作数值型
  • 逻辑操作不会产生短路

8. Math的floor、round、ceil函数区别

floor

向下取整,返回不大于的最大整数

ceil

向上取整,则是不小于他的最小整数

round

四舍五入,入的时候是到大于它的整数(当-1.5时,四舍五入后得到的结果不是我们期待的,解决办法是先对他取绝对值,然后在用round方法)

round方法,算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整,所以,Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。

正数小数点后大于5则进位;负数小数点后小于以及等于5都舍去,大于5的则进位。

如希望-11.5四舍五入结果为-12,则先对它取绝对值,然后在用round方法,再乘以-1。

示例

Math.floor Math.round Math.ceil
1.4 1 1 2
1.5 1 2 2
1.6 1 2 2
-1.4 -2 -1 -1
-1.5 -2 -1 -1
-1.6 -2 -2 -1

9. 求2*8的最效率方法

2 << 3

10. 有没有length()这个方法

数组没有length()这个方法,有length 的属性。

String 有length()这个方法。

11. swtich中表达式的类型

intshortchar 或者 byte可以出现在switch中的表达式里。

String类型在 JDK 1.7 之后可以出现在switch中的表达式里。

12. Java中如何跳出多重嵌套循环

在最外层循环前加 label 标识,然后用 break:label 方法即可跳出多重循环。

13. 构造器Constructor 是否可被override

构造器Constructor 不能被继承,因此不能重写Overriding,但可以被重载Overloading。

14. x.equals(y) == true; hashcode是否相同

相同。

15. 是否可以继承String 类

String 类是final 类,故不可以继承。

16. equals()和equalsIgnoreCase()的区别

equals()函数

主要是区分“比较的字符串” 大小写和长度时候相同,比较的类型可以是Object类型。

equalsIgnoreCase()函数

比较的参数只能是字符串,这里只要字符串的长度相等,字母的大小写是忽略的。认为A-Z和a-z是一样的。

17. 值传递还是引用传递

问:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

答:是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。

18. char型变量中能否存储一个中文汉字

能够定义成为一个中文的,因为Java 中以unicode 编码,一个char 占16个字节,所以放一个中文是没问题的。

19. abstract class和interface有什么区别

声明方法的存在而不去实现它的类被叫做抽象类(abstract class)。然而可以创建一个变量,其类型是一个抽象类,它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。

接口(interface)是抽象类的变体。新型多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,所有成员变量都是publicstatic final 的。一个类可以实现多个接口,当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,

instanceof 运算符可以用来决定某对象的类是否实现了接口。

20. Static Nested Class和Inner Class的不同

Static Nested Class 是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。

而通常的内部类需要在外部类实例化后才能实例化。

21. Java中是否存在内存泄漏

内存泄漏是指不再被使用的对象或者变量一直被占据在内存中。但是java中有垃圾回收机制,它能够将不再被使用的对象,自动从内存中清除。

即使这样,java中也存在着内存泄漏的情况:

一:当长生命周期的对象持有短生命周期的对象的引用,就很可能发生内存泄漏。尽管短生命周期的对象已经不再需要,但是长生命周期的对象一直持有它的引用导致其无法被回收。例如,缓存系统;加载一个对象放在缓存系统中,一直不去使用这个对象,但是它一直被缓存引用,所以不会被回收导致缓存泄漏。

检查java中的内存泄漏,一定要将程序各个分支情况都完成执行至结束,然后看其是否被使用过,如果没有才能判定这个对象属于内存泄漏。

二:当一个对象被存储进HashSet集合中,就不可修改这个对象中用于计算哈希值的属性了。否则,对象修改后的哈希值与刚添加进HashSet集合时的哈希值不一样,此时如果将当前对象的引用作为参数,用contains方法判断对象是否存在,则会返回找不到对象的结果。这会导致无法从HashSet单独删除当前对象,造成内存泄漏。

22. 静态变量和实例变量的区别

静态变量也称为类变量,归全类共有,它不依赖于某个对象,可通过类名直接访问;而实例变量必须依存于某一实例,只能通过对象才能访问到它。

23. 写clone()方法时通常都有一行代码,是什么

Clone 有缺省行为:super.clone();,它负责产生正确大小的空间,并逐位复制。

24. GC是什么,为什么要有GC

GC 是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java 提供的GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java 语言没有提供释放已分配内存的显示操作方法。

Java 程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc()Runtime.getRuntime().gc()

25. 垃圾回收的优点和原理

Java 语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java 程序员在编写程序的时候不再需要考虑内存管理。

由于有垃圾回收机制,Java 中的对象不再有“作用域”的概念,只有对象的引用才有“作用域”。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。

垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。

回收机制有分代复制垃圾回收标记垃圾回收增量垃圾回收

26. 垃圾回收器的基本原理是什么

垃圾回收器的基本原理是什么?

答:对于GC 来说,当程序员创建对象时,GC 就开始监控这个对象的地址、大小以及使用情况。通常,GC 采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC 确定一些对象为"不可达"时,GC 就有责任回收这些内存空间。

垃圾回收器可以马上回收内存吗?

答:可以。

有什么办法主动通知虚拟机进行垃圾回收?

答:程序员可以手动执行System.gc(),通知GC 运行,但是Java 语言规范并不保证GC 一定会执行。

27. String s=new String(“xyz”);创建了几个String对象

两个对象,一个是"xyx",一个是指向"xyx"的引用对象s。

上面解释不够详细准确,准确解释可详读《String、StringBuffer、StringBuilder的区别》

28. 接口与抽象类的相互继承问题

接口是否可继承接口?

答:接口可以继承接口。

抽象类是否可实现(implements)接口?

答:抽象类可以实现(implements)接口。

抽象类是否可继承实体类(concrete class)?

答:抽象类可继承实体类,但前提是实体类必须有明确的构造函数。

29. Java的接口和C++的虚类的相同和不同处

由于Java 不支持多继承,而有可能某个类或对象要使用分别在几个类或对象里面的方法或属性,现有的单继承机制就不能满足要求。与继承相比,接口有更高的灵活性,因为接口中没有任何实现代码。当一个类实现了接口以后,该类要实现接口里面所有的方法和属性,并且接口里面的属性在默认状态下面都是public static,所有方法默认情况下是public。一个类可以实现多个接口。

30. 一个Java源文件中是否可以包含多个类(非内部类)

可以;必须只有一个类名与文件名相同。

31. 内部类是否可以引用外部类的成员

一个内部类对象可以访问创建它的外部类对象的内容。

32. Java中实现多态的机制是什么

方法的覆盖Overriding 和重载Overloading 是 Java 多态性的不同表现。

覆盖Overriding 是父类与子类之间多态性的一种表现。

重载Overloading 是一个类中多态性的一种表现。

33. 数据类型之间的转换

如何将数值型字符转换为数字?

答:调用数值类型相应包装类中的方法parse*(String)或valueOf(String)即可返回相应基本类型或包装类型数值。

如何将数字转换为字符?

答:将数字与空字符串相加即可获得其所对应的字符串;另外对于基本类型数字还可调用String 类中的valueOf(…)方法返回相应字符串,而对于包装类型数字则可调用其toString()方法获得相应字符串。

如何取小数点前两位并四舍五入?

答:可用该数字构造一java.math.BigDecimal 对象,再利用其round()方法进行四舍五入到保留小数点后两位,再将其转换为字符串截取最后两位。

34. 如何实现字符串的反转及替换

可用字符串构造一StringBuffer 对象,然后调用StringBuffer 中的 reverse 方法即可实现字符串的反转,调用 replace 方法即可实现字符串的替换。

35. 日期和时间

如何取得年月日、小时分秒?

答:创建java.util.Calendar 实例(Calendar.getInstance()),,调用其get()方法传入不同的参数即可获得参数所对应的值,如:

calendar.get(Calendar.YEAR); // 获得年

如何取得从1970 年到现在的毫秒数?

答:以下方法均可获得该毫秒数:

Calendar.getInstance().getTimeInMillis();
System.currentTimeMillis();

如何取得某个日期是当月的最后一天?

答:示例代码如下:

Calendar time = Calendar.getInstance();
time.set(Calendar.DAY_OF_MONTH,
time.getActualMaximum(Calendar.DAY_OF_MONTH));

如何格式化日期?

利用java.text.DataFormat 类中的format()方法可将日期格式化。

36. Java和JavaSciprt的区别

JavaScript 与Java 是两个公司开发的不同的两个产品。

Java 是SUN 公司推出的新一代面向对象的程序设计语言,特别适合于Internet 应用程序开发;而JavaScript 是Netscape 公司的产品,其目的是为了扩展Netscape Navigator功能,而开发的一种可以嵌入Web 页面中的基于对象和事件驱动的解释性语言,它的前身是Live Script;而Java 的前身是Oak 语言。

下面对两种语言间的异同作如下比较:

  1. 基于对象和面向对象:Java 是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象;JavaScript 是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。它是一种基于对象(Object Based)和事件驱动(Event Driver)的编程语言。因而它本身提供了非常丰富的内部对象供设计人员使用;
  2. 解释和编译:Java 的源代码在执行之前,必须经过编译;JavaScript 是一种解释性编程语言,其源代码不需经过编译,由浏览器解释执行;
  3. 强类型变量和类型弱变量:Java 采用强类型变量检查,即所有变量在编译之前必须作声明;JavaScript 中变量声明,采用其弱类型。即变量在使用前不需作声明,而是解释器在运行时检查其数据类型;
  4. 代码格式不一样。

37. 什么时候用assert

assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。一般来说,assertion 用于保证程序最基本、关键的正确性。assertion 检查通常在开发和测试时开启。为了提高性能,在软件发布后, assertion 检查通常是关闭的。

在实现中,断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为true;如果表达式计算为false,那么系统会报告一个Assertionerror。

断言用于调试目的:

assert(a > 0); // throws an Assertionerror if a <= 0

断言可以有两种形式:

assert Expression1 ;
assert Expression1 : Expression2 ;

Expression1 应该总是产生一个布尔值。

Expression2 可以是得出一个值的任意表达式;这个值用于生成显示更多调试信息的String 消息。

断言在默认情况下是禁用的,要在编译时启用断言,需使用source 1.4 标记:

javac -source 1.4 Test.java

要在运行时启用断言,可使用-enableassertions 或者-ea 标记。

要在运行时选择禁用断言,可使用-da 或者-disableassertions 标记。

要在系统类中启用断言,可使用-esa 或者-dsa 标记。

还可以在包的基础上启用或者禁用断言。

可以在预计正常情况下不会到达的任何位置上放置断言。

断言可以用于验证传递给私有方法的参数。

不过,断言不应该用于验证传递给公有方法的参数,因为不管是否启用了断言,公有方法都必须检查其参数。不过,既可以在公有方法中,也可以在非公有方法中利用断言测试后置条件。另外,断言不应该以任何方式改变程序的状态。

results matching ""

    No results matching ""