东方国信(实习一面)

  1. String s = “Hello”;s = s + " world!";这两行代码执行后,原始的String对象中的内容到底变了没有?
  2. Spring常用注解总结
  3. 线程池
  4. 抽象类和接口的区别
  5. 异常
  6. java文件是如何编译的
  7. GC何时进行?GC触发的时机
  8. synchronized和volatile的区别

String s = “Hello”;s = s + " world!";这两行代码执行后,原始的String对象中的内容到底变了没有?
没有。因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。在这段代码中,s原先指向一个String对象,内容是 “Hello”,然后我们对s进行了+操作,这时,s不指向原来那个对象了,而指向了另一个 String对象,内容为"Hello world!",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。s所指向的那个对象并没有发生改变。


Spring常用注解总结


项目中用到了事务吧,怎么实现的?
用JdbcTemplate,是spring提供的一个jdbc的框架,使用简单,在代码中写sql,比较灵活

  1. 导入依赖
    在这里插入图片描述
  2. spring配置文件在这里插入图片描述
  3. 使用jdbcTemplate写一个业务
    在这里插入图片描述

标准答案:
声明式事务→注解(最简单、最方便、最好用、最重要)
注解写在哪里,哪里就增加事务

首先要打开注解开关:
在这里插入图片描述


使用注解:
@Transactional
在这里插入图片描述


Spring事务管理主要包括3个接口,Spring的事务主要是由他们三个共同完成的,其中的PlatformTransactionManager是Spring事务管理的核心接口!这三个事务管理器接口是根据指定的传播行为,返回当前活动的事务,或者创建一个新的事务,参数的类定义一些基本的事务属性。

PlatformTransactionManager,是Spring事务管理的核心接口。主要功能是事务管理器,是用于平台相关事务的管理,包括commit 事务的提交;rollback 事务的回滚;getTransaction 事务状态的获取三种方法。

TransactionDefinition,主要功能是事务定义信息,是用来定义事务相关的属性,给事务管理器PlatformTransactionManager使用的。而且在TransactionDefinition接口中定义了它自己的传播行为和隔离级别。包括getIsolationLevel:获取隔离级别;getPropagationBehavior:获取传播行为;getTimeout:获取超时时间;isReadOnly:是否只读 四种方法。

TransactionStatus,主要功能是事务具体运行状态,是事务管理过程中,每个时间点事务的状态信息,它可以封装许多代码,节省我们的工作量。包括hasSavepoint():返回这个事务内部是否包含一个保存点;isCompleted():返回该事务是否已完成,也就是说,是否已经提交或回滚;isNewTransaction():判断当前事务是否是一个新事务 这三种方法。


线程池
在这里插入图片描述


抽象类和接口的区别。

抽象类:包含有抽象方法的类 或 被abstract修饰的类

特征:
1.抽象类不能直接实例化,但是抽象类可以间接实例化:
抽象类类型 引用 = new 具体子类();

2.抽象类的子类:
a. 可以是具体类 (子类必须覆盖实现抽象父类中,所有的抽象方法)
b. 抽象类的子类可以是抽象类 (当子类没有覆盖并实现,抽象父类中所有的抽象方法)

注意事项:
a. 有抽象方法的类一定是抽象类
b. 抽象类不一定有抽象方法

abstract不能和哪些关键字共存
private
final
static
对于为什么冲突的理解:

abstract 定义抽象方法,对于抽象方法而言,如果在代码中要使用,其实永远是通过多态,调用的是子类中,覆盖实现的抽象父类的抽象方法

而被,private,final,static关键字修饰的方法,都不能在子类中被覆盖,于是意味着这些方法,无法在程序中运行。

接口:
侧重于描述,一组具有特殊 功能 的行为,这些行为,可以完全没有任何关系。接口中的方法,它们的关系比较的松散

接口不能直接实例化(接口中,对于方法,只能有抽象方法)
a. 不能直接实例化一个接口(new 接口)
b. 接口可以间接实例化
接口类型的 引用 = new 接口实现子类()
MyInterface inter = new InterfaceClass()

抽象类和接口的比较
成员区别
抽象类 成员变量:没有任何限制;
成员方法:有抽象方法; 非抽象方法

接口 成员变量:只能是常量,默认修饰符 public static final;
成员方法:必须是抽象方法(jdk7及以前成立)

关系区别
类与类(包括普通类和抽象类) 继承关系,单继承
类与接口 实现关系, 单实现(实现一个接口),多实现(实现多个接口)
接口与接口 继承关系,单继承,多继承

设计理念区别
抽象类 被其他类继承体现的是:“is a”的关系。表示共性功能
接口 被实现体现的是:”like a”的关系。扩展功能


异常
jvm默认异常处理流程
a. 当我们代码在执行到,发生错误的地方。
b. 一旦发生错误,jvm就会终止我们自己程序的运行,不会执行错误程序后面的代码,转而执行jvm自己的错误处理流程
c. 在发生错误地方,收集错误信息,产生一个描述错误的对象
基本格式:try是检测异常,catch是用来捕获异常的,finally是用来结束资源的


java文件是如何编译的:
java语言的特点:
高级语言计算机本身是不认识的,计算机只认识二进制01,一定有一个工具,帮助我们将我们的程序转化为计算机可以识别的对应到机器指令级别的二进制序列。
1.编译型语言:用这种语言写出的代码,首先通过编译器的编译,全部转化成目标代码(二进制可执行文件 .exe),然后依次在操作系统中执行。
2.解释型语言:转化一句,执行一句

java语言是解释型的:.java(java源代码)—>.class(字节码文件)—>jvm,jvm对.class转化一句,执行一句。
在这里插入图片描述

java具有健壮性:没有指针、提供异常机制(让你有机会对自己的错误进行修复)
java具有动态性:动态加在字节码文件运行。
分布式:java语言天生对网络通信有很好的的支持,易于实现分布式。


GC何时进行?GC触发的时机:
a. 申请heap space失败后会触发GC回收(何时会申请失败呢?例如堆满时)
b. 系统进入idle(空闲)后一段时间会进行回收
c. 主动调用GC进行回收(调用System.gc)


synchronized和volatile的区别:
在这里插入图片描述
volatile是一个类型修饰符。它被设计用来修饰被不同的线程访问和修改的变量值。
volatile的作用: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。

  • volatile不需要加锁,比synchronized更轻量级,不会阻塞线程;

  • 从内存可见性角度,volatile读相当于加锁,volatile写相当于解锁;

  • synchronized既能够保证可见性,又能保证原子性,而volatile只能保证可见性,无法保证原子性。

  • volatile仅能使用在变量级别,synchronized则可以使用在变量、方法、类级别上。

volatile:不会加锁,不会造成阻塞,能保证可见性,不能保证原子性,不如synchronized安全
synchronized:会加锁,会造成阻塞,能保证可见性,能保证原子性

基于 volatile 关键字来实现线程间相互通信是使用共享内存的思想,大致意思就是多个线程同时监听一个变量,当这个变量发生变化的时候 ,线程能够感知并执行相应的业务。这也是最简单的一种实现方式

public class TestSync {
    // 定义一个共享变量来实现通信,它需要是volatile修饰,否则线程不能及时感知
    static volatile boolean notice = false;

    public static void main(String[] args) {
        List<String>  list = new ArrayList<>();
        // 实现线程A
        Thread threadA = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                list.add("abc");
                System.out.println("线程A向list中添加一个元素,此时list中的元素个数为:" + list.size());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (list.size() == 5)
                    notice = true;
            }
        });
        // 实现线程B
        Thread threadB = new Thread(() -> {
            while (true) {
                if (notice) {
                    System.out.println("线程B收到通知,开始执行自己的业务...");
                    break;
                }
            }
        });
        // 需要先启动线程B
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 再启动线程A
        threadA.start();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-玫瑰少年-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值