Java面试季一 (1)

简介: Java面试季一

JavaSE 面试题

1、自增变量

public static void main(String[] args) {
        int i = 1;
        i = i++;
        int j = i++;
        int k = i + ++i * i++;
        System.out.println("i=" + i);
        System.out.println("j=" + j);
        System.out.println("k=" + k);
    }
123456789

image.png

执行 i = i++; 先将i变量压入操作数栈,然再对i变量进行自增,最后把计算结果赋值给 i , i 任然是1

i++ 计算后将值给到 j

image.png

最后一步

image.png

执行结果

i=4
j=1
k=11
123

2、单例模式

什么事Singleton?

Singleton:在Java中 即指单例设置模式,探视软件开发最常用的设置模式之一

单:唯一

例:实例

单例设计模式,即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式

例如:代表JVM运行环境的Runtime类

要点:

一是某个类只能有一个实例

构造器私有化

二是他必须自行创建实例

含有一个该类的静态变量来保存这个唯一的实例

三是它必须自行向整个系统提供这个实例

对外提供获取该类实例对象的方式

  • 直接暴露
  • 用静态变量的get方法获取

几种常见形式

饿汉式:直接创建对象,不存在线程安全问题

直接实例化饿汉式(简洁直观)

枚举式 (最简洁)

静态代码块饿汉式(适合复杂实例化)

懒汉式;延迟创建对象

线程不安全(使用于单线程)

线程安全(使用于多线程)

静态内部类模式 (适用于多线程)

饿汉式

直接实例化饿汉式(简洁直观)
public class Singleton1 {
    /**
     * 1、构造器私有化
     * 2、自行创建,并且用静态变量保存
     * 3、向外提供实例
     * 4、强调这是一个单例,我们可以用final修改
     */
    private Singleton1() {
    }
    public static final Singleton1 INSTANCE = new Singleton1();
}
12345678910111213
枚举式 (最简洁)
public enum  Singleton2 {
    /**
     * 枚举类型:表示该类型是有限的几个
     */
    INSTANCE
}
123456
静态代码块饿汉式(适合复杂实例化)
public class Singleton3 {
    /**
     *  静态代码块
     */
    public static final Singleton3 INSTANCE;
    private String info;
    static {
        try {
            INSTANCE = new Singleton3("123");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    private Singleton3(String info) {
        this.info = info;
    }
}
12345678910111213141516171819

懒汉式

线程不安全(使用于单线程)
public class Singleton4 {
    /**
     * 1、构造器私有化
     * 2、用一个静态变量保存这个唯一的实例
     * 3、提供一个静态方法,获取这个实例对象
     */
    static Singleton4 instance;
    private Singleton4() {}
    public static Singleton4 getInstance() {
            if (instance == null) {
                instance = new Singleton4();
            }
            return instance;
    }
}
1234567891011121314151617
线程安全(使用于多线程)
public class Singleton5 {
    /**
     * 1、构造器私有化
     * 2、用一个静态变量保存这个唯一的实例
     * 3、提供一个静态方法,获取这个实例对象
     */
    static Singleton5 instance;
    private Singleton5() {}
    public static Singleton5 getInstance() {
        if (instance == null) {
            synchronized (Singleton5.class) {
                if (instance == null) {
                    instance = new Singleton5();
                }
                return instance;
            }
        }
        return instance;
    }
}
123456789101112131415161718192021
静态内部类模式 (适用于多线程)
public class Singleton6 {
    /**
     * 1、内部类被加载和初始化时,才创建INSTANCE实例对象
     * 2、静态内部类不会自动创建,随着外部类的加载初始化而初始化,他是要单独去加载和实例化的
     * 3、因为是在内部类加载和初始化时,创建的,因此线程安全
     */
    private Singleton6(){}
    public static class Inner{
        private static final Singleton6 INSTANCE = new Singleton6();
    }
    public static Singleton6 getInstance() {
        return Inner.INSTANCE;
    }
}
123456789101112131415

3、类初始化实例初始化

类初始化

一个类要创建实例需要先加载并初始化该类

main方法所在的类需要先加载和初始化

一个子类要初始化需要先初始化父类

一个类初始化就是执行 clinit 方法

clinit 方法由静态类变量显示赋值代码和静态代码块组成

类变量显示赋值代码和静态代码块代码从上到下执行

clinit 方法只调用一次

实例初始化过程

实例初始化就是执行 init() 方法

init () 方法可能重载有多个,有几个构造器就有几个 init() 方法

init() 方法由非静态实例变量显示赋值代码和非静态代码块,对应构造器代码组成

非静态实例变量显示赋值代码和非静态代码块从上到下顺序执行,而对应构造器的代码最后执行

每次创建实例对象,调用对应构造器,执行的就是对应的 ini方法

init 方法的首行是super()和super(实参列表) ,即对应父类的 init 方法

Father.java
package com.atguigu.classLoader;
/**
 * 父类初始化<clinit>
 * 1、j = method()
 * 2、 父类的静态代码块
 *
 * 父类实例化方法:
 * 1、super()(最前)
 * 2、i = test() (9)
 * 3、子类的非静态代码块 (3)
 * 4、子类的无参构造(最后)(2)
 *
 *
 * 非静态方法前面其实有一个默认的对象this
 * this在构造器或<init> 他表示的是正在创建的对象,因为咱们这里是正在创建Son对象,所以
 * test()执行的就是子类重写的代码(面向对象多态)
 *
 * 这里i=test() 执行的就是子类重写的test()方法
 * @author gcq
 * @Create 2020-09-25
 */
public class Father {
    private int i = test();
    private static int j = method();
    static{
        System.out.println("(1)");
    }
    Father() {
        System.out.println("(2)");
    }
    {
        System.out.println("(3)");
    }
    public int test(){
        System.out.println("(4)");
        return 1;
    }
    public static int method() {
        System.out.println("(5)");
        return 1;
    }
}
1234567891011121314151617181920212223242526272829303132333435363738394041424344
Son.java
package com.atguigu.classLoader;
/**
 * 子类的初始化<clinit>
 * 1、j = method()
 * 2、子类的静态代码块
 *
 * 先初始化父类 (5)(1)
 * 初始化子类 (10) (6)
 *
 * 子类实例化方法:
 * 1、super()(最前
 * 2、i = test() (9)
 * 3、子类的非静态代码块 (8)
 * 4、子类的无参构造(最后)(7)
 * @author gcq
 * @Create 2020-09-25
 */
public class Son extends Father {
    private int i = test();
    private static int j = method();
    static {
        System.out.println("(6)");
    }
    Son() {
        super();
        System.out.println("(7)");
    }
    {
        System.out.println("(8)");
    }
    public int test(){
        System.out.println("(9)");
        return 1;
    }
    public static int method() {
        System.out.println("(10)");
        return 1;
    }
    public static void main(String[] args) {
        Son son = new Son();
        System.out.println();
        Son son1 = new Son();
    }
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546

执行结果

(5)
(1)
(10)
(6)
(9)
(3)
(2)
(9)
(8)
(7)
(9)
(3)
(2)
(9)
(8)
(7)
1234567891011121314151617

4、方法参数传递机制

代码:

package com.atguigu.methodParam;
import java.util.Arrays;
/**
 * @author gcq
 * @Create 2020-09-28
 */
public class Exam4 {
    public static void main(String[] args) {
        int i = 1;
        String str = "hello";
        Integer num = 200;
        int[] arr = {1,2,3,4,5};
        MyData my = new MyData();
        change(i,str,num,arr,my);
        // arr my变了
        System.out.println("i= " + i);
        System.out.println("str= " + str);
        System.out.println("num= " + num);
        System.out.println("arr= " + Arrays.toString(arr));
        System.out.println("my.a= " + my.a);
    }
    public static void change(int j, String s, Integer n, int[] a, MyData m) {
        j += 1;
        s += "world";
        n += 1;
        a[0] += 1;
        m.a += 1;
    }
}
class MyData {
    int a = 10;
}
1234567891011121314151617181920212223242526272829303132333435363738

考点?

方法的参数传递机制

String、包装类等对象的不可变性

方法的参数传递机制

1、形参是基本数据类型

  • 传递数据值

2、实参是引用数据类型

  • 传递地址值

特殊的类型:String、包装类等对象的不可变性

<<<<<<< Updated upstream

image.png

输出结果

i= 1
str= hello
num= 200
arr= [2, 2, 3, 4, 5]
my.a= 11
12345

5、递归与迭代 && 暂时不理解

6、成员变量和局部变量

考点?

就近原则

变量的分类

成员变量: 类变量、实例变量

局部变量

非静态代码块的执行:每次创建实例对象都会执行

方法的调用规则:调用一次执行一次

局部变量与成员变量区别:

1、声明的位置

局部变量:方法体{}中,形参,代码块{}中

成员变量:类方法外

类变量: 有static修饰

实例变量:没有static修饰

2、修饰符

局部变量:final

成员变量:public protected,private,final ,static volatile,transient

3、值存储位置

局部变量:栈

实例变量:堆

类变量:方法区

image.png

堆(Heap) ,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。

通常所说的栈(Stack) ,是指虚拟机栈。虚拟机栈用于存储局部变量表等。局部变量

表存放了编译期可知长度的各种基本数据类型(boolean、byte、 char、short、 int、 float、long、double) 、对象引用(reference 类型,它不等同于对象本身,是对象在堆内存的首地址)。方法执行完, 自动释放。

方法区(Method Area)用于存储已被虛拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

4、作用域:

局部变量从声明处开始,到所属的 } 好结束

实例变量:在当前类中 this 有时this. 可以省略,在其他类中 对象名. 访问

类变量:在当前类中 类名 有时类名. 可以省略,在其它类中类名.或对象名.访问

5、生命周期

局部变量:每一个线程,每一次调用执行都是新的生命周期

实例变量:随着对象的创建而初始化,随着对象的被回收而消亡,每一个对象的实例变量都是独立的

类变量:随着类的初始化而初始化,随着类的卸载而消亡,该类的所有对象的类变量是共享的

当局部变量与XX变量重名时,如何区分:

1、局部变量与实例变量重名

  • 在成员便令前面加 this

2、局部变量与类变量重名

  • 在类变量前面加 类名/**
  • @author gcq
  • @Create 2020-09-29 */ public class Exam5 { static int s;// 5 int i; // A-2  B-1 int j;//A-1 B-1 { int i = 1; i++; // 就近原则 j++; s++; } public void test(int j) { j++; // 就近原则 21 i++; s++; } public static void main(String[] args){ Exam5 obj1 = new Exam5(); Exam5 obj2 = new Exam5(); obj1.test(10); obj1.test(20); obj2.test(30); // 2 1 5 System.out.println(obj1.i + "," + obj1.j + "," + obj1.s); // 1 1 5 System.out.println(obj2.i + "," + obj2.j + "," + obj2.s); } } 12345678910111213141516171819202122232425262728293031

image.png

SSM面试题

Spring中支持的常用数据库事务传播属性和事务隔离级别

1 事务的传播行为

1.1 简介

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播,列如方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行,事务传播的行为有传播属性指定,Spring定义了7中类传播行为

传播属性

描述

REQUIRED

如果有事务在运行,当前的方法就在这个事务内运行,否则就启动一个新的事务,并在自己的事务内运行

REQUIRED_NEW

当前方法必须启动事务,并在它自己的事务内运行,如果有事务正在运行,应该将他挂起

SUPPORTS

如果有事务在运行,当前的方法就在这个事务内运行,否则他可以不运行在事务中

NOT_SUPPORTE

当前的方法不应该运行在事务中,如果有运行的事务,将他挂起

MANDATORY

当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常

NEVER

当前方法不应该运行在事务中,如果有运行的事务,就抛出异常

NESTED

如果有事务在运行,当前的方法就应该在这个事物的嵌套事务内运行,否则,就启动一个新的事务,并在它自己的事务内运行

事务传播属性可以在@Transactional注解的propagation属性中定义

2 事务隔离级别

2.1 数据库事务并发问题

假设现在有两个事务:Transaction01和Transaction02并发执行。

1) 脏读

①Transaction01将某条记录的AGE值从20修改为30。

②Transaction02读取了Transaction01更新后的值:30。

③Transaction01回滚,AGE值恢复到了20。

④Transaction02读取到的30就是一个无效的值。

2) 不可重复读

①Transaction01读取了AGE值为20。

②Transaction02将AGE值修改为30。

③Transaction01再次读取AGE值为30,和第一次读取不一致。

3) 幻读

①Transaction01读取了STUDENT表中的一部分数据。

②Transaction02向STUDENT表中插入了新的行。

③Transaction01读取了STUDENT表时,多出了一些行。

2.2 隔离级别

数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。

  1. 读未提交:READ UNCOMMITTED

允许Transaction01读取Transaction02未提交的修改。

  1. 读已提交:READ COMMITTED

要求Transaction01只能读取Transaction02已提交的修改。

  1. 可重复读:REPEATABLE READ

确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更新。

  1. 串行化:SERIALIZABLE

确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其它事务对这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能十分低下。

  1. 各个隔离级别解决并发问题的能力见下表

image.png

总结

//1.请简单介绍Spring支持的常用数据库事务传播属性和事务隔离级别?
  /**
   * 事务的属性:
   *  1.★propagation:用来设置事务的传播行为
   *    事务的传播行为:一个方法运行在了一个开启了事务的方法中时,当前方法是使用原来的事务还是开启一个新的事务
   *    -Propagation.REQUIRED:默认值,使用原来的事务
   *    -Propagation.REQUIRES_NEW:将原来的事务挂起,开启一个新的事务
   *  2.★isolation:用来设置事务的隔离级别
   *    -Isolation.REPEATABLE_READ:可重复读,MySQL默认的隔离级别
   *    -Isolation.READ_COMMITTED:读已提交,Oracle默认的隔离级别,开发时通常使用的隔离级别
   */
123456789101112



目录
相关文章
|
19天前
|
缓存 Java 关系型数据库
【Java面试题汇总】ElasticSearch篇(2023版)
倒排索引、MySQL和ES一致性、ES近实时、ES集群的节点、分片、搭建、脑裂、调优。
【Java面试题汇总】ElasticSearch篇(2023版)
|
19天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
174 37
|
19天前
|
设计模式 安全 算法
【Java面试题汇总】设计模式篇(2023版)
谈谈你对设计模式的理解、七大原则、单例模式、工厂模式、代理模式、模板模式、观察者模式、JDK中用到的设计模式、Spring中用到的设计模式
【Java面试题汇总】设计模式篇(2023版)
|
19天前
|
存储 关系型数据库 MySQL
【Java面试题汇总】MySQL数据库篇(2023版)
聚簇索引和非聚簇索引、索引的底层数据结构、B树和B+树、MySQL为什么不用红黑树而用B+树、数据库引擎有哪些、InnoDB的MVCC、乐观锁和悲观锁、ACID、事务隔离级别、MySQL主从同步、MySQL调优
【Java面试题汇总】MySQL数据库篇(2023版)
|
19天前
|
存储 缓存 NoSQL
【Java面试题汇总】Redis篇(2023版)
Redis的数据类型、zset底层实现、持久化策略、分布式锁、缓存穿透、击穿、雪崩的区别、双写一致性、主从同步机制、单线程架构、高可用、缓存淘汰策略、Redis事务是否满足ACID、如何排查Redis中的慢查询
【Java面试题汇总】Redis篇(2023版)
|
19天前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
19天前
|
缓存 Java 数据库
【Java面试题汇总】Spring篇(2023版)
IoC、DI、aop、事务、为什么不建议@Transactional、事务传播级别、@Autowired和@Resource注解的区别、BeanFactory和FactoryBean的区别、Bean的作用域,以及默认的作用域、Bean的生命周期、循环依赖、三级缓存、
【Java面试题汇总】Spring篇(2023版)
|
19天前
|
存储 缓存 监控
【Java面试题汇总】JVM篇(2023版)
JVM内存模型、双亲委派模型、类加载机制、内存溢出、垃圾回收机制、内存泄漏、垃圾回收流程、垃圾回收器、G1、CMS、JVM调优
【Java面试题汇总】JVM篇(2023版)
|
19天前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
8天前
|
消息中间件 NoSQL Java
Java知识要点及面试题
该文档涵盖Java后端开发的关键知识点,包括Java基础、JVM、多线程、MySQL、Redis、Spring框架、Spring Cloud、Kafka及分布式系统设计。针对每个主题,文档列举了重要概念及面试常问问题,帮助读者全面掌握相关技术并准备面试。例如,Java基础部分涉及面向对象编程、数据类型、异常处理等;JVM部分则讲解内存结构、类加载机制及垃圾回收算法。此外,还介绍了多线程的生命周期、同步机制及线程池使用,数据库设计与优化,以及分布式系统中的微服务、RPC调用和负载均衡等。
下一篇
无影云桌面