1,Java 中的数据类型有哪些?
基本数据类型:
-
整数类型:byte,short,int,long
-
浮点类型:float,double
-
字符类型:char
-
布尔类型:boolean
引用数据类型:
-
类(Class)
-
接口(Interface)
-
数组(Array)
-
枚举(Enum)
-
注解(Annotation)
2,如何实现 Java 中的多态?
-
继承:多态必须基于继承的概念,在java中,继承的过程是通过extends关键字实现的
-
抽象:多态必须依赖抽象的概念,在java中,抽象的过程可以通过抽象类或者接口来实现
-
重写:多态的实现必须要通过重写的概念,在java中,重写的过程是通过@Override注解标识的
3,Java 中的 try-catch 机制是什么?有什么用处?
使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。 try下面表示可能出现异常的代码,而catch里面这是如果这些代码出现了异常改如何处理。当然,如果你在catch中没有做任何处理,那么虚拟机就会什么都不做然后继续运行下面的代码。如果你不用try...catch,那么当程序出现异常时会抛到虚拟机那里,最终导致程序终止!
4,Java 中的异常处理有哪些常见的异常?
下面的表中列出了 Java 的非检查性异常。
异常 | 描述 |
ArithmeticException | 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。 |
ArrayIndexOutOfBoundsException | 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。 |
ArrayStoreException | 试图将错误类型的对象存储到一个对象数组时抛出的异常。 |
ClassCastException | 当试图将对象强制转换为不是实例的子类时,抛出该异常。 |
IllegalArgumentException | 抛出的异常表明向方法传递了一个不合法或不正确的参数。 |
IllegalMonitorStateException | 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。 |
IllegalStateException | 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。 |
IllegalThreadStateException | 线程没有处于请求操作所要求的适当状态时抛出的异常。 |
IndexOutOfBoundsException | 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 |
NegativeArraySizeException | 如果应用程序试图创建大小为负的数组,则抛出该异常。 |
NullPointerException | 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 |
NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 |
SecurityException | 由安全管理器抛出的异常,指示存在安全侵犯。 |
StringIndexOutOfBoundsException | 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。 |
UnsupportedOperationException | 当不支持请求的操作时,抛出该异常。 |
下面的表中列出了 Java 定义在 java.lang 包中的检查性异常类。
异常 | 描述 |
ClassNotFoundException | 应用程序试图加载类时,找不到相应的类,抛出该异常。 |
CloneNotSupportedException | 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。 |
IllegalAccessException | 拒绝访问一个类的时候,抛出该异常。 |
InstantiationException | 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。 |
InterruptedException | 一个线程被另一个线程中断,抛出该异常。 |
NoSuchFieldException | 请求的变量不存在 |
NoSuchMethodException | 请求的方法不存在 |
5, 什么 是 Java 中的接口?为什么要使用接口?
-
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
-
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
-
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
-
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
interface Animal {
public void eat();
public void travel();
}
接口与类相似点:
-
一个接口可以有多个方法。
-
接口文件保存在 .java 结尾的文件中,文件名使用接口名。
-
接口的字节码文件保存在 .class 结尾的文件中。
-
接口相应的字节码文件必须在与包名称相匹配的目录结构中。
接口与类的区别:
-
接口不能用于实例化对象。
-
接口没有构造方法。
-
接口中所有的方法必须是抽象方法,Java 8 之后 接口中可以使用 default 关键字修饰的非抽象方法。
-
接口不能包含成员变量,除了 static 和 final 变量。
-
接口不是被类继承了,而是要被类实现。
-
接口支持多继承。
接口特性
-
接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
-
接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
-
接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
抽象类和接口的区别
-
1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
-
2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
-
3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
-
4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
6,Java 中的继承是什么?它的好处是什么?
继承的概念
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
继承的特性
-
子类拥有父类非 private 的属性、方法。
-
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
-
子类可以用自己的方式实现父类的方法。
-
Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
-
提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
继承关键字
继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承 Object祖先类。
class 父类 {
}
class 子类 extends 父类 {
}
7,Java 中的 抽象类是什么?它与接口有什么区别?
-
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
-
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
-
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
-
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
-
在 Java 中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
public abstract class Employee
{
private String name;
private String address;
private int number;
public Employee(String name, String address, int number)
{
System.out.println("Constructing an Employee");
this.name = name;
this.address = address;
this.number = number;
}
public double computePay()
{
System.out.println("Inside Employee computePay");
return 0.0;
}
public void mailCheck()
{
System.out.println("Mailing a check to " + this.name
+ " " + this.address);
}
public String toString()
{
return name + " " + address + " " + number;
}
public String getName()
{
return name;
}
public String getAddress()
{
return address;
}
public void setAddress(String newAddress)
{
address = newAddress;
}
public int getNumber()
{
return number;
}
}
抽象类总结规定
-
1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
-
2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
-
3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
-
4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
-
5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
抽象类和接口的区别
-
1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
-
2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
-
3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
-
4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
8,Java 中的泛型是什么?它的用处是什么?
Java 泛型
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
java 中泛型标记符:
-
E - Element (在集合中使用,因为集合中存放的是元素)
-
T - Type(Java 类)
-
K - Key(键)
-
V - Value(值)
-
N - Number(数值类型)
-
? - 表示不确定的 java 类型
9,什么是 Java 中的自动装箱和拆箱?
装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
int i0 = 0; //创建基础类型
Integer i1 = i0; //自动装箱
int i2 = i1; //自动拆箱
10,详细描述 Java 中的多线程
Java 多线程编程
Java 给多线程编程提供了内置的支持。 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。
这里定义和线程相关的另一个术语 - 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。
多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。
一个线程的生命周期
线程是一个动态执行的过程,它也有一个从产生到死亡的过程。
-
新建状态:
使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
-
就绪状态:
当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
-
运行状态:
如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
-
阻塞状态:
如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
-
等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
-
同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
-
其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
-
死亡状态:
一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。
11,Java 中的 单例模式是什么?如何实现单例模式?
单例模式
单例模式是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
-
单例类只能有一个实例。
-
单例类必须自己创建自己的唯一实例。
-
单例类必须给所有其他对象提供这一实例。
12,什么是面向对象? 面向对象的三大特征是什么?
对象的含义是指具体的某一个事物,即在现实生活中能够看得见摸得着的事物。在面向对象程序设计中,对象所指的是计算机系统中的某一个成分。在面向对象程序设计中,对象包含两个含义,其中一个是数据,另外一个是动作。对象则是数据和动作的结合体。对象不仅能够进行操作,同时还能够及时记录下操作结果。
三大基本特征
面向对象的三大基本特征:封装,继承,多态
封装
所谓封装,就是把客观的事物封装为抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的类或对象隐藏信息
继承
继承,继承指它可以使用现有类的所有功能,并在无须编写原来的类的情况下对这些功能进行拓展,通过继承创建的新类(子类),被继承的类(父类)
多态
多态:指一个类实例的相同方法在不同情形下有不同的表现形式
使得有不同内部结构的对象可以共享相同的外部接口
13,什 么是封装?它的好处是什么?
Java 封装
-
在面向对象程式设计方法中,封装是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。
-
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
-
要访问该类的代码和数据,必须通过严格的接口控制。
-
封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
-
适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。
封装的优点
-
良好的封装能够减少耦合。
-
类内部的结构可以自由修改。
-
可以对成员变量进行更精确的控制。
-
隐藏信息,实现细节。
14,什么是多态?它的好处是什 么?
Java 多态
多态是同一个行为具有多个不同表现形式或形态的能力。
多态的优点
-
消除类型之间的耦合关系
-
可替换性
-
可扩充性
-
接口性
-
灵活性
-
简化性
多态存在的三个必要条件
-
继承
-
重写
-
父类引用指向子类对象:Parent p = new Child();
15,什么是方法重载?
-
方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。
-
调用重载方法时,Java编译器能通过检查调用的方法的参数类型和个数选择一个恰当的方法。
-
方法重载通常用于创建完成一组任务相似但参数的类型或参数的个数或参数的顺序不同的方法。
-
Java的方法重载,就是在类中可以创建多个方法,它们可以有相同的名字,但必须具有不同的参数,即或者是参数的个数不同,或者是参数的类型不同。
-
调用方法时通过传递给它们的不同个数和类型的参数,以及传入参数的顺序来决定具体使用哪个方法。
16,什么是抽象方法?
java中的抽象方法就是以abstract修饰的方法,这种方法只声明返回的数据类型、方法名称和所需的参数,没有方法体,也就是说抽象方法只需要声明而不需要实现。
public abstract class Employee
{
private String name;
private String address;
private int number;
public abstract double computePay();
//其余代码
}
17, 什么是静态代码块?它的用处是什么?
格式:
static {
静态代码块的内容
} 静态块用于初始化类,为类的属性初始化。每个静态代码块只会执行一次。静态代码块随着类加载而加载,有多个静态代码块的,按代码块前后顺序加载。由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法执行。
18,请简要描述 Java 的关键字 super 和 this 的作用。
this
this 是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。
this 的用法在 Java 中大体可以分为3种:
普通的直接引用
这种就不用讲了,this 相当于是指向当前对象本身。
形参与成员名字重名,用 this 来区分:
class Person {
private int age = 10;
public Person(){
System.out.println("初始化年龄:"+age);
}
public int GetAge(int age){
this.age = age;
return this.age;
}
}
public class test1 {
public static void main(String[] args) {
Person Harry = new Person();
System.out.println("Harry's age is "+Harry.GetAge(12));
}
}
可以看到,这里 age 是 GetAge 成员方法的形参,this.age 是 Person 类的成员变量。
super
super 可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。
super 也有三种用法:
普通的直接引用
与 this 类似,super 相当于是指向当前对象的父类,这样就可以用 super.xxx 来引用父类的成员。
子类中的成员变量或方法与父类中的成员变量或方法同名
class Country {
String name;
void value() {
name = "China";
}
}
class City extends Country {
String name;
void value() {
name = "Shanghai";
super.value(); //调用父类的方法
System.out.println(name);
System.out.println(super.name);
}
public static void main(String[] args) {
City c=new City();
c.value();
}
}
可以看到,这里既调用了父类的方法,也调用了父类的变量。若不调用父类方法 value(),只调用父类变量 name 的话,则父类 name 值为默认值 null。
引用构造函数
-
super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
-
this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。
class Person {
public static void prt(String s) {
System.out.println(s);
}
Person() {
prt("父类·无参数构造方法: "+"A Person.");
}//构造方法(1)
Person(String name) {
prt("父类·含一个参数的构造方法: "+"A person's name is " + name);
}//构造方法(2)
}
public class Chinese extends Person {
Chinese() {
super(); // 调用父类构造方法(1)
prt("子类·调用父类"无参数构造方法": "+"A chinese coder.");
}
Chinese(String name) {
super(name);// 调用父类具有相同形参的构造方法(2)
prt("子类·调用父类"含一个参数的构造方法": "+"his name is " + name);
}
Chinese(String name, int age) {
this(name);// 调用具有相同形参的构造方法(3)
prt("子类:调用子类具有相同形参的构造方法:his age is " + age);
}
public static void main(String[] args) {
Chinese cn = new Chinese();
cn = new Chinese("codersai");
cn = new Chinese("codersai", 18);
}
}
从本例可以看到,可以用 super 和 this 分别调用父类的构造方法和本类中其他形式的构造方法。
例子中 Chinese 类第三种构造方法调用的是本类中第二种构造方法,而第二种构造方法是调用父类的,因此也要先调用父类的构造方法,再调用本类中第二种,最后是重写第三种构造方法。
super 和 this的异同
-
super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句)
-
this(参数):调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)
-
super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参) this:它代表当前对象名(在程序中易产生二义性之处,应使用 this 来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用 this 来指明成员变量名)
-
调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用 super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。
-
super() 和 this() 类似,区别是,super() 从子类中调用父类的构造方法,this() 在同一类内调用其它方法。
-
super() 和 this() 均需放在构造方法内第一行。
-
尽管可以用this调用一个构造器,但却不能调用两个。
-
this 和 super 不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有 super 语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
-
this() 和 super() 都指的是对象,所以,均不可以在 static 环境中使用。包括:static 变量,static 方法,static 语句块。
-
从本质上讲,this 是一个指向本对象的指针, 然而 super 是一个 Java 关键字。
19,什么是包装类?它的作用是什么?
包装类把基本类型数据转换为对象
每个基本类型在java.lang包中都有一个相应的包装类
基本数据类型及对应的包装类
基本数据类型 | 对应的包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
boolean | Boolean |
包装类有何作用:
提供了一系列实用的方法集合不允许存放基本数据类型数据,存放数字时,要用包装类型
所有包装类都可将与之对应的基本数据类型作为参数,来构造它们的实例
如:Integer i=new Integer(1);
除Character类外,其他包装类可将一个字符串作为参数构造它们的实例
如: Integer i=new Integer("123");
基本类型和对应的包装类可以相互装换:
-
由基本类型向对应的包装类转换称为装箱,例如把 int 包装成 Integer 类的对象;
-
包装类向对应的基本类型转换称为拆箱,例如把 Integer 类的对象重新简化为 int。