我将从基础概念、进阶知识、高阶应用等方面出发,结合阿里Java面试常见考点,为你呈现一份全面的学习指南,希望能助你顺利通过面试。
阿里Java面试必刷100题:从基础到高阶,助你通关终面
一、基础概念夯实
1.1 Java基础语法
- 数据类型:Java的数据类型分为基本数据类型(如byte、short、int、long、float、double、char、boolean)和引用数据类型(类、接口、数组等)。例如,在定义一个整数变量时:
int num = 10;
,这里int
就是基本数据类型。基本数据类型存储在栈内存中,数据直接存储值;而引用数据类型存储在堆内存中,栈中存储的是对象的引用地址。 - 运算符:包括算术运算符(+、-、*、/、%等)、赋值运算符(=、+=、-=等)、比较运算符(==、!=、>、<等)、逻辑运算符(&&、||、!)等。如判断两个数大小:
int a = 5, b = 3; boolean result = a > b;
,这里>
就是比较运算符,&&
逻辑与运算符常用于多个条件同时满足的判断,如if (a > 0 && b < 10)
。 - 流程控制语句:有顺序结构、选择结构(if - else、switch - case)和循环结构(for、while、do - while)。比如使用
for
循环打印1到10的数字:
for (int i = 1; i <= 10; i++) {
System.out.println(i);
}
if - else
语句用于条件判断后的不同执行分支,如if (a > 5) { System.out.println("大于5"); } else { System.out.println("小于等于5"); }
。
1.2 面向对象编程
- 类与对象:类是对象的模板,对象是类的实例。例如定义一个
Person
类:
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void sayHello() {
System.out.println("大家好,我叫" + name + ",今年" + age + "岁。");
}
}
创建对象:Person person = new Person("张三", 20); person.sayHello();
,通过new
关键字创建对象,并调用对象的方法。
2. 封装:通过将类的属性私有化(使用private
修饰符),并提供公共的访问方法(getter和setter方法)来实现封装。如上述Person
类中,name
和age
属性被私有化,通过getName
和getAge
等方法来访问和修改。
3. 继承:子类可以继承父类的属性和方法,使用extends
关键字。例如定义一个Student
类继承自Person
类:
class Student extends Person {
private String school;
public Student(String name, int age, String school) {
super(name, age);
this.school = school;
}
public void study() {
System.out.println(name + "在" + school + "学习。");
}
}
这里Student
类继承了Person
类的属性和方法,还添加了自己特有的school
属性和study
方法。
4. 多态:多态性体现在方法的重载(同一个类中方法名相同,参数列表不同)和重写(子类重写父类的方法)。例如在Person
类基础上,Student
类重写sayHello
方法:
class Student extends Person {
// 省略其他代码
@Override
public void sayHello() {
System.out.println("我是学生" + name + ",我在" + school + "上学。");
}
}
当使用Person
类型引用指向Student
对象时,调用sayHello
方法会执行Student
类中重写后的方法,体现了多态性。
1.3 集合框架
- List接口:有序可重复的集合。常见的实现类有
ArrayList
和LinkedList
。ArrayList
基于数组实现,查询效率高,增删操作在非尾部时效率低;LinkedList
基于链表实现,增删操作效率高,查询效率低。例如:
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
int num = list.get(0);
- Set接口:无序不可重复的集合。常用的实现类有
HashSet
和TreeSet
。HashSet
基于哈希表实现,插入和查找效率高;TreeSet
基于红黑树实现,可对元素进行排序。如:
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
boolean contains = set.contains("apple");
- Map接口:存储键值对,键唯一。常见实现类有
HashMap
、TreeMap
和ConcurrentHashMap
。HashMap
非线程安全,基于哈希表;TreeMap
可对键进行排序;ConcurrentHashMap
线程安全,适用于高并发场景。例如:
Map<String, Integer> map = new HashMap<>();
map.put("one", 1);
map.put("two", 2);
int value = map.get("one");
二、进阶知识巩固
2.1 多线程与并发
- 线程创建方式:有继承
Thread
类和实现Runnable
接口两种方式。继承Thread
类:
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程运行中");
}
}
MyThread thread = new MyThread();
thread.start();
实现Runnable
接口:
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("线程运行中");
}
}
MyRunnable runnable = new MyRunnable();
Thread thread2 = new Thread(runnable);
thread2.start();
- 线程同步机制:为解决多线程并发访问共享资源的线程安全问题,可使用
synchronized
关键字、Lock
接口等。例如使用synchronized
修饰方法实现同步:
class SynchronizedExample {
private int count = 0;
public synchronized void increment() {
count++;
}
}
Lock
接口提供了更灵活的锁控制,如ReentrantLock
:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class LockExample {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
- 线程池:线程池可复用线程,减少线程创建和销毁开销,提高系统性能。常见线程池如
ThreadPoolExecutor
,可通过Executors
工具类创建不同类型线程池,如固定大小线程池Executors.newFixedThreadPool(int nThreads)
:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executorService.submit(() -> {
System.out.println(Thread.currentThread().getName() + "正在执行任务");
});
}
executorService.shutdown();
2.2 异常处理
- 异常体系:Java异常分为
Checked Exception
(受检异常,如IOException
、SQLException
等,必须显式捕获或抛出)和Unchecked Exception
(非受检异常,包括RuntimeException
及其子类,如NullPointerException
、ArrayIndexOutOfBoundsException
等,可不显式处理)。Exception
类是所有异常的父类,Error
类表示系统错误,如OutOfMemoryError
,一般不由程序处理。 - 异常处理机制:使用
try - catch - finally
块处理异常。try
块中放置可能抛出异常的代码,catch
块捕获并处理异常,finally
块无论是否发生异常都会执行。例如:
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("捕获到算术异常:" + e.getMessage());
} finally {
System.out.println("finally块执行");
}
也可通过throws
关键字在方法声明处抛出异常,由调用者处理。例如:
public void readFile() throws IOException {
// 文件读取代码可能抛出IOException
}
2.3 反射机制
- 反射的概念:反射允许程序在运行时获取类的信息(如类的属性、方法、构造函数等),并动态创建对象、调用方法等。例如获取一个类的
Class
对象:
Class<?> clazz = String.class;
// 或通过对象获取
String str = "hello";
Class<?> clazz2 = str.getClass();
// 或通过类名获取
try {
Class<?> clazz3 = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
- 反射的应用场景:在框架开发(如Spring通过反射创建和管理Bean)、动态加载类、调用私有方法等场景中广泛应用。例如通过反射创建对象:
try {
Class<?> clazz = Class.forName("com.example.Person");
Object obj = clazz.getConstructor(String.class, int.class).newInstance("张三", 20);
if (obj instanceof Person) {
Person person = (Person) obj;
person.sayHello();
}
} catch (Exception e) {
e.printStackTrace();
}
这里通过反射获取Person
类的构造函数,并创建对象调用方法。
三、高阶应用提升
3.1 设计模式
- 单例模式:确保一个类只有一个实例,并提供全局访问点。常见实现方式有饿汉式和懒汉式。饿汉式在类加载时就创建实例:
class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
懒汉式在第一次调用getInstance
方法时创建实例,需注意线程安全问题,可通过双重检查锁实现线程安全的懒汉式:
class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
- 工厂模式:将对象的创建和使用分离,提高代码的可维护性和可扩展性。简单工厂模式通过一个工厂类创建对象,例如创建不同类型的图形:
interface Shape {
void draw();
}
class Circle implements Shape {
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("绘制矩形");
}
}
class ShapeFactory {
public static Shape createShape(String type) {
if ("circle".equals(type)) {
return new Circle();
} else if ("rectangle".equals(type)) {
return new Rectangle();
}
return null;
}
}
使用时:Shape shape = ShapeFactory.createShape("circle"); shape.draw();
3. 代理模式:为其他对象提供一种代理以控制对这个对象的访问。例如动态代理,通过InvocationHandler
接口和Proxy
类实现,假设要对一个UserService
接口的实现类进行代理增强:
interface UserService {
void sayHello();
}
class UserServiceImpl implements UserService {
@Override
public void sayHello() {
System.out.println("Hello, User!");
}
}
class ProxyHandler implements InvocationHandler {
private Object target;
public ProxyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法调用前增强");
Object result = method.invoke(target, args);
System.out.println("方法调用后增强");
return result;
}
}
class ProxyFactory {
public static Object createProxy(Object target) {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new ProxyHandler(target)
);
}
}
使用时:UserService userService = new UserServiceImpl(); UserService proxyService = (UserService) ProxyFactory.createProxy(userService); proxyService.sayHello();
3.2 微服务架构
- Spring Cloud组件:Spring Cloud是一套微服务框架,包含多个组件。
Eureka
用于服务注册与发现,服务提供者将自己注册到Eureka Server
,服务消费者从Eureka Server
获取服务列表。例如在服务提供者项目中配置Eureka
:
在pom.xml
添加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring - cloud - starter - netflix - eureka - client</artifactId>
</dependency>
在application.yml
配置:
server:
port: 8081
eureka:
client:
service - url:
defaultZone: http://localhost:8761/eureka/
启动类添加注解@EnableEurekaClient
。
Ribbon
用于客户端负载均衡,它会从Eureka Server
获取服务列表,并根据负载均衡算法选择一个服务实例进行调用。Feign
是声明式的Web服务客户端,可通过接口定义和注解简化服务调用,例如定义一个调用其他服务的Feign
接口:
@FeignClient(name = "service - name")
interface OtherServiceClient {
@GetMapping("/api/hello")
String sayHello();
}
- 分布式事务:在微服务架构中,多个服务可能参与一个业务事务,保证分布式事务一致性是关键。可使用
Seata
等框架解决分布式事务问题。Seata
提供了AT
、TCC
等事务模式。以AT
模式为例,在项目中引入Seata
依赖:
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata - spring - boot - starter</artifactId>
</dependency>
配置Seata
相关参数,如事务组名称等。在业务方法上添加@GlobalTransactional
注解标识分布式事务,例如:
@Service
public class OrderService {
@GlobalTransactional
public void createOrder() {
// 业务逻辑,可能涉及多个服务调用
}
}
3.3 性能优化
- JVM调优:通过调整JVM参数(如堆大小、新生代与老年代比例、垃圾回收器等)来优化性能。例如设置堆初始大小和最大大小为2GB:
-Xms2g -Xmx2g
,选择G1垃圾回收器:-XX:+UseG1GC
。可通过分析GC日志(使用-Xlog:gc*
参数开启日志)了解垃圾回收情况,如新生代和老年代的回收次数、回收时间等,进而调整参数。 - 代码优化:减少不必要的对象创建,如使用对象池(如
commons - pool2
库实现的对象池)复用对象;优化算法和数据结构,例如在查找操作频繁时,将ArrayList
替换为HashSet
或HashMap
以提高查找效率;合理使用缓存,如在应用中引入Redis
缓存热点数据,减少数据库查询次数。例如使用Redis
缓存用户信息:
import redis.clients.jedis.Jedis;
public class UserCache {
private Jedis jedis;
public UserCache() {
jedis = new Jedis("localhost", 6379);
}
public String getUserFromCache(String userId) {
return jedis.get("user:" + userId);
}
public void setUserToCache(String userId, String userInfo) {
jedis.set("user:" + userId, userInfo);
}
}
通过对这100题涉及的从基础到高阶知识的学习和实践,不断积累和总结,在面试中就能更加自信从容,顺利通关终面,开启在阿里的精彩职业之旅。
代码获取方式
关注我获取更多内容