这是初级程序员要掌握的Java最基础知识,中,高级就更不必说了,下一篇介绍中,高级程序员面试中Java18问。
1.java的数据类型有哪些?
原始数据类型
java中的有8种原始数据类型:
- byte:表示8位带符号的整数,取值范围为-128到127。
- short:表示16位带符号的整数,取值范围为-32768到32767。
- int:表示32位带符号的整数,取值范围为-2147483648到2147483647。
- long:表示64位带符号的整数,取值范围为-9223372036854775808到9223372036854775807。
- float:表示32位浮点数。
- double:表示64位双精度浮点数。
- char:表示16位unicode字符,取值范围为'\u0000'到'\uffff'。
- boolean:表示布尔类型,只有两个值true和false。
引用数据类型
java中的所有非原始数据类型都属于引用数据类型。例如:
- 类
- 接口
- 数组
- 字符串
2. 什么是java的自动装箱和拆箱?
Java中的自动装箱(Autoboxing)和拆箱(Unboxing)是Java编程语言中的两个重要概念。它们是让基本数据类型和包装类型之间进行转换的方便机制。
自动装箱(Autoboxing)
自动装箱是指将一个基本数据类型转换为相应的包装类型,这个过程是自动完成的。例如,将int型变量i赋值给Integer类型的变量j时,编译器会自动将i转换为Integer类型。
示例代码:
int i = 10;
Integer j = i; // 自动装箱
自动拆箱(Unboxing)
自动拆箱是指将一个包装类型转换为相应的基本数据类型,这个过程也是自动完成的。例如,将Integer类型的变量j赋值给int型变量i时,编译器会自动将j转换为int类型。
示例代码:
Integer j = 10;
int i = j; // 自动拆箱
自动装箱和拆箱使得我们可以像使用基本数据类型一样使用包装类型,这种机制减少了代码的冗余和复杂度,提高了程序的可读性和可维护性。但是在某些情况下,也可能会导致性能问题。因此,在使用自动装箱和拆箱时,需要谨慎考虑。
3.java集合有哪些?它们有什么特点?
java中提供了很多种集合类,常见的有以下几种:
list(列表)
特点:有序、可重复,可以通过索引访问元素。
常见实现类:arraylist、linkedlist、vector。
arraylist适用于大量随机访问元素的情况,linkedlist适用于频繁**、删除元素的情况;
set(集合)
特点:无序、不可重复,不能通过索引访问元素。
常见实现类:hashset、linkedhashset、treeset。
hashset适用于不需要按照顺序访问元素的情况
treeset适用于需要排序的情况
queue(队列)
特点:根据规则进行**和删除,并且具有先进先出的特性。
常见实现类:arraydeque、concurrentlinkedqueue、priorityqueue。
priorityqueue适用于需要在队列中根据优先级排序的情况
map(映射)
特点:以键值对的形式存储数据,键是唯一的,值可以重复,通过键访问值。
常见实现类:hashmap、linkedhashmap、treemap。
hashmap适用于快速查找元素的情况
treemap适用于需要按照键排序的情况
通过选择合适的集合类,可以更加高效地处理数据和算法问题。
4. 什么是java的反射机制?它有什么用途?
java反射机制
java反射是指在运行时动态地获取对象的信息和操作对象的行为的机制。它允许程序通过“反射”来调用 java 类的方法、字段和构造函数等属性,甚至可以获取类的所有信息。与传统编程方式不同,java反射允许在运行时分析类和对象,从而提供更灵活的编程方式。
java反射机制包含了下面几个重要的类和接口:
- class:表示一种类型的java类
- method:表示java类中的方法
- field:表示java类中的属性
- constructor:表示java类中的构造器
反射机制的作用
java 反射机制有很多用途,其中比较常见的包括:
- 通过反射获得某个类的全部信息,比如类名,父类信息,实现接口信息,字段,方法等。
- 动态创建对象: 使用反射可以在运行时通过类名获得类对象,并且使用该对象可以创建新的实例对象。
- 调用对象的方法: 使用反射可以动态调用对象的方法,使代码更加灵活。
- 访问或设置对象的字段: 使用反射可以获取或者设置一个对象的私有字段的值,即便在正常情况下也不能直接访问。
- 对于框架开发者, 使用反射可以很方便的将配置文件映射成相应的对象类型。
- 利用反射机制,可以在运行时处理注解信息,实现动态注入等功能。
总之,java 反射机制提供了一种强大、灵活的方式来访问和操作类信息、对象实例以及相关数据。 但反射也会导致性能问题,因此在使用时应
5.java异常处理机制是怎样的?
Java异常处理机制使程序员能够编写代码,以在程序执行期间检测和响应错误。当程序发生错误时,它会生成一个异常对象。这个异常对象包含有关错误的信息,并将它传递给调用者或抛出到当前执行堆栈中的相应的异常处理程序。
Java异常处理机制主要由以下几个部分组成:
try-catch块
try-catch块是一种结构化的方式来控制异常,它用于捕获可能会在代码块中引发的异常。try块中包含可能会引发异常的代码,而catch块则定义了如何处理异常。如果try块中的代码引发了一个异常,Java虚拟机就会查找与该异常匹配的catch块,并执行其中的代码。
复制代码try {
// 可能引发异常的代码
} catch (ExceptionType e) {
// 处理异常的代码
}
异常类
异常类是表示不同类型异常的类。Java有许多内置的异常类,例如NullPointerException、
ArrayIndexOutOfBoundsException等。程序员也可以自己定义异常类。
public class MyException extends Exception {
public MyException(String message) {
super(message);
}
}
throw语句
throw语句用于抛出异常,它将一个异常对象传递给运行时系统。当执行到throw语句时,程序停止执行当前方法并传递异常对象到调用方法的地方。
public void myMethod() throws MyException {
if (somethingIsWrong) {
throw new MyException("Something went wrong!");
}
}
throws语句
throws语句用于声明一个方法可能引发的异常。如果一个方法可能会引发一个已检查的异常,那么它必须声明该异常或它的父类在方法头部使用throws语句。
public void myMethod() throws IOException {
// 可能抛出IOException异常的代码
}
总之,Java异常处理机制使得程序员能够更好地控制程序错误,并提高了程序的健壮性和可靠性。
6. 如何实现多线程程序?线程和进程有什么区别?
Java可以通过实现
java.util.concurrent.Callable接口或者继承java.lang.Thread类来实现多线程程序。
实现Callable接口
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class MyThread implements Callable {
@Override
public Integer call() throws Exception {
int sum = 0; for (int i = 0; i < 10; i++)
{
sum += i;
System.out.println(Thread.currentThread().getName() + " calculates sum: " + sum);
} return sum;
}
public static void main(String[] args) throws Exception
{
FutureTask futureTask = new FutureTask<>(new MyThread());
Thread thread = new Thread(futureTask, "mythread");
thread.start();
System.out.println(futureTask.get());
}
}
继承Thread类
public class MyThread extends Thread {
@Override
public void run() {
int sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
System.out.println(Thread.currentThread().getName() + " calculates sum: " + sum);
}
}
public static void main(String[] args) {
Thread thread = new MyThread(); thread.start();
}
}
线程和进程的主要区别在于,进程是操作系统资源分配的最小单位,而线程是CPU调度的最小单位。也就是说,在一个进程中可以有多个线程,并且这些线程共享进程的资源,例如堆、方法区和静态变量等。由于线程是共享进程的资源的,所以处理同一数据时,同步问题需要特别处理。而不同进程间相互独立,彼此不影响。
7. java中的关键字final、static有什么作用?
final
final 关键字可以用于修饰不可修改的常量、方法或类。
- 修饰变量:声明一个常量,该变量必须在声明时已经被初始化,一旦赋值不能再改变。
final int age = 25;
- 修饰方法:声明方法不可被子类重写。
public final void myMethod() { // 方法体 }
- 修饰类:声明一个不可继承的类。
public final class MyClass { // 类内容 }
static
static 关键字可以修饰变量、方法和代码块,用于表示这些成员属于类,而不是属于实例对象。
- 修饰变量:被称之为“静态变量”或“类变量”,只存在于类的内存中,也就是说每个实例对象都共享此变量。
public static int instanceCount; // 类变量
- 修饰方法:被称之为“静态方法”,不能使用类的非静态变量,因为它们只能访问静态变量。调用时不需要创建实例对象。
public static void printName(String name) { System.out.println("Name: " + name); }
- 修饰代码块:被称为“静态代码块”,在类的加载时执行,并且只会执行一次。
static { // 静态代码块 }
static 关键字的使用主要有以下几个方面:
- 可以直接通过类名进行访问;
- 可以用来做单例模式,以节省内
8.解释一下java的访问修饰符:public、protected、default、private?
java中的访问修饰符用于描述类、方法和变量的可见性。下面是各种访问修饰符的含义:
public
公共访问级别,该类、方法或变量可以被任何类访问
例如:public class myclass{} 或者 public void mymethod(){}
protected
受保护访问级别,该类、方法或变量可以被同一包中的其他类访问,子类也可以访问
例如:protected int myvariable; 或者 protected void mymethod(){}
default (没有关键字)
包级别访问,该类、方法或变量可以被同一包中的其他类访问
例如:class myclass{} 或者 int myvariable;
private
私有访问级别,该类、方法或变量只能在该类内部访问
例如:private int myvariable; 或者 private void mymethod(){}
注意:以上四种访问修饰符必须放在类定义的最前面。默认的访问修饰符是default,如果没有明确指定,则使用默认值。
9.java中常见的23种设计模式,先简要给出后续再补充具体模式的实现及代码案例
- 工厂方法模式(factory method)
- 抽象工厂模式(abstract factory)
- 单例模式(singleton)
- 建造者模式(builder)
- 原型模式(prototype)
- 适配器模式(adapter)
- 桥接模式(bridge)
- 过滤器模式(filter)
- 组合模式(composite)
- 装饰器模式(decorator)
- 外观模式(facade)
- 享元模式(flyweight)
- 代理模式(proxy)
- 责任链模式(chain of responsibility)
- 命令模式(command)
- 解释器模式(interpreter)
- 迭代器模式(iterator)
- 中介者模式(mediator)
- 备忘录模式(memento)
- 观察者模式(observer)
- 状态模式(state)
- 策略模式(strategy)
- 模板方法模式(template method)
10.什么是java的序列化和反序列化?为什么要进行序列化和反序列化?
Java的序列化是将Java对象转换为字节流以便在网络上传输或在本地存储。反序列化则是将这些字节流重新转换回Java对象。序列化和反序列化可通过Java中的ObjectOutputStream和ObjectInputStream类实现。
进行序列化和反序列化的主要原因是在分布式系统中进行远程方法调用(RPC)和数据持久化。序列化后的对象可以跨网络传输并在不同的Java虚拟机之间进行通信,或者存储到文件系统或数据库中以便之后检索和使用。
11.什么是java内存泄漏?如何避免内存泄漏?
Java内存泄漏是指在Java应用程序中,因为某些对象不再被使用但仍然占用内存空间而导致内存无法被回收的情况。
常见的内存泄漏原因包括:
- 对象没有被正确地释放。比如,未关闭数据库连接或文件流。
- 静态集合类(如HashMap)导致的内存泄漏。如果添加到这样的集合中的对象没有被正确地移除,那么它们将一直存在于内存中。
- 对象被错误地缓存导致的内存泄漏。如果将大量对象缓存到内存中,而这些对象却永远不会被访问到,那么就会导致内存泄漏。
避免内存泄漏的方法包括:
- 及时关闭数据库连接、文件流和其它需要手动释放资源的对象。
- 使用WeakReference和SoftReference等引用类型来避免静态集合类导致的内存泄漏。
- 定期清理缓存,以确保只有必要的对象才存在于内存中。
- 使用垃圾回收器(Garbage Collector)来及时回收不再使用的对象。
- 使用专业的工具进行内存泄漏检测和分析,如Eclipse Memory Analyzer(MAT)和VisualVM。
12.类与接口的异同点?
相同点:
都是Java编程语言中的基本构造块,可以用于定义对象或数据类型,并且都可以包含方法、属性和构造函数。
差异点:
- 类可以被实例化为对象,而接口不能。
- 类可以继承另一个类或者实现多个接口,而接口只能继承另一个接口,并且一个类可以实现多个接口。
- 类可以包含实例变量,而接口不能。接口只能包含静态常量。
- 类可以有构造函数,而接口没有。
- 方法实现的方式不同。在类中,方法可以有具体的实现,而在接口中,所有的方法都是抽象方法,即没有具体实现的方法。从Java 8开始,接口可以包含默认方法和静态方法,这些方法可以有具体实现。
- 访问修饰符的使用也不同。类中的方法和变量可以使用public、protected、private和默认访问修饰符进行修饰,而接口中的方法和变量只能使用public和默认访问修饰符。
13.java中的静态成员和静态方法有什么特点?
- 静态成员属于类,而不是属于对象。因此,在创建类的任何实例之前,静态成员已经存在。
- 静态成员可以通过类名直接访问,不需要通过对象来访问。
- 静态方法也属于类,而不是属于对象,因此可以通过类名直接调用。
- 静态方法不能访问非静态成员或非静态方法,因为非静态成员和方法需要依赖于对象才能访问。
- 静态成员和静态方法可以被所有对象共享,因此修改一个静态成员或调用一个静态方法会影响所有对象。
- 静态成员和静态方法可以用来跟踪类级别的信息,例如统计类的实例数量或记录最大的实例ID等。
14.java中的泛型有什么作用?如何使用泛型?
Java中的泛型可以使代码更加通用和类型安全。使用泛型可以将类型作为参数传递给类、接口、方法等,从而使得这些结构能够适用于不同的数据类型,而不需要重复编写相似的代码。
在Java中,可以使用尖括号(<>)来定义泛型类型或泛型方法。例如,可以定义一个泛型类:
public class MyClass {
private T value;
public void setValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
在上面的示例中,T是一个占位符,表示类型参数。当实例化MyClass时,可以将具体的类型作为参数传递给T,例如:
MyClass myClass = new MyClass<>();
myClass.setValue("Hello, world!");
String value = myClass.getValue();
在上面的示例中,MyClass
通过使用泛型,可以避免一些类型转换的问题,并提高代码的可读性和可维护性。
15.try-catch-finally语句是如何工作的?
try-catch-finally语句块用于处理可能会抛出异常的代码。其工作方式如下:
- 首先执行try语句块中的代码。
- 如果在执行try语句块中的代码时发生了异常,则跳转到与该异常匹配的catch语句块中。如果没有与异常匹配的catch语句块,则异常将向上抛出。
- 如果try语句块中的代码成功执行完毕,或者在catch语句块中处理了异常,则继续执行finally语句块中的代码。无论是否发生异常,finally语句块中的代码都会被执行。
try-catch-finally语句块可以确保资源得到正确关闭,例如打开的文件或者网络连接,在finally语句块中可以释放这些资源。
16.Object中有几个方法,并分别介绍其作用?
Object类是所有Java类的基类,它提供了一些通用的方法,包括:
- equals(Object obj):比较当前对象和另一个对象是否相等,返回一个布尔值。默认情况下,该方法使用“==”比较两个对象的地址是否相等,但通常需要重写该方法来比较对象的内容是否相等。
- hashCode():返回当前对象的哈希码值,用于在哈希表中查找对象。通常需要重写该方法来确保相等的对象具有相等的哈希码。
- toString():返回当前对象的字符串表示,通常用于调试和日志记录。
- getClass():返回当前对象所属的类的Class对象。
- wait()、notify()、notifyAll():这些方法用于线程间的通信和同步,可以在多线程编程中使用。
- finalize():当对象被垃圾回收器回收时,会自动调用该方法,可以在该方法中进行一些清理工作。
除了以上方法,Object还提供了一些其他的方法,如clone()、finalize()等,但这些方法通常需要重写才能使用。
17.为什么要重写equals和hashcode方法?
equals和hashCode方法是用来判断两个对象是否相等的重要方法。默认情况下,equals方法比较的是两个对象的引用是否相等,而hashCode方法返回的是对象的内存地址。
然而,在实际应用中,我们通常需要比较对象的属性是否相等,而不是比较对象的引用是否相等。这时候就需要重写equals和hashCode方法,以便让它们比较对象的属性。
重写equals和hashCode方法的好处有:
- 可以根据对象的属性来比较对象是否相等,而不是比较对象的引用是否相等。
- 可以保证对象在使用HashSet、HashMap等集合类时能够正确地工作。
- 重写equals方法后,还应该重写hashCode方法,以便让它们一起工作。如果不重写hashCode方法,就不能保证在使用HashSet、HashMap等集合类时能够正确地工作。
18.项目案例?
自由发挥喽
这是初级程序员应该要掌握的Java最基础知识,中,高级就更不必说了,下一篇介绍中,高级程序员面试中Java18问。
本文暂时没有评论,来添加一个吧(●'◡'●)