如下代码的运算结果:
package java_one; /** * @author parzulpan * @version 1.0 * @date 2021-04 * @project JavaInterview * @package java_one * @desc 自增变量 * i = 1 * i = 2 j = 1 * i = 4 k = 11 * i = 4 k = 1 k = 11 */ public class IncreasingVariable { 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); } }
总结:
实现如下:
package java_one; /** * @author parzulpan * @version 1.0 * @date 2021-04 * @project JavaInterview * @package java_one * @desc 2.单例设计模式 * 饿汉式 - 直接实例化 * 在类初始化时直接创建实例对象,不管是否需要这个对象都会创建 * 1. 构造器私有化 * 2. 自行创建,并用公有静态变量保存 * 3. 向外提供这个实例 */ public class Singleton1 { public static final Singleton1 INSTANCE = new Singleton1(); private Singleton1() { } }
测试代码:
class Singleton1Test { public static void main(String[] args) { Singleton1 s1 = Singleton1.INSTANCE; Singleton1 s2 = Singleton1.INSTANCE; System.out.println(s1 == s2); System.out.println(s1); System.out.println(s2); } }
实现如下:
package java_one; /** * @author parzulpan * @version 1.0 * @date 2021-04 * @project JavaInterview * @package java_one * @desc 2.单例设计模式 * 饿汉式 - 枚举式 * 枚举类型表示该类型的对象是有限的几个,可以限定为一个,就成了单例 */ public enum Singleton2 { INSTANCE }
测试代码:
class Singleton2Test { public static void main(String[] args) { Singleton2 s1 = Singleton2.INSTANCE; Singleton2 s2 = Singleton2.INSTANCE; System.out.println(s1 == s2); System.out.println(s1); System.out.println(s2); } }
实现如下:
package java_one; /** * @author parzulpan * @version 1.0 * @date 2021-04 * @project JavaInterview * @package java_one * @desc 2.单例设计模式 * 饿汉式 - 静态代码块 * 这种方式通常适用于复杂的实例化 */ public class Singleton3 { public static final Singleton3 INSTANCE; static { // ... INSTANCE = new Singleton3(); } }
测试代码:
class Singleton3Test { public static void main(String[] args) { Singleton3 s1 = Singleton3.INSTANCE; Singleton3 s2 = Singleton3.INSTANCE; System.out.println(s1 == s2); System.out.println(s1); System.out.println(s2); } }
实现如下:
package java_one; /** * @author parzulpan * @version 1.0 * @date 2021-04 * @project JavaInterview * @package java_one * @desc 2.单例设计模式 * 懒汉式 - 线程不安全,适用于单线程 * 延迟创建实例对象 * 1. 构造器私有化 * 2. 用一个私有静态变量保存这个唯一的实例 * 3. 提供一个静态方法,获取这个实例对象 */ public class Singleton4 { private static Singleton4 instance; private Singleton4() { } public static Singleton4 getInstance() { if (instance == null) { // ... try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } instance = new Singleton4(); } return instance; } }
测试代码:
class Singleton4Test { public static void main(String[] args) throws ExecutionException, InterruptedException { Callable<Singleton4> callable = new Callable<Singleton4>() { @Override public Singleton4 call() throws Exception { return Singleton4.getInstance(); } }; ExecutorService executorService = Executors.newFixedThreadPool(2); Future<Singleton4> future1 = executorService.submit(callable); Future<Singleton4> future2 = executorService.submit(callable); Singleton4 s1 = future1.get(); Singleton4 s2 = future2.get(); System.out.println(s1 == s2); System.out.println(s1); System.out.println(s2); executorService.shutdown(); } }
实现如下:
package java_one; /** * @author parzulpan * @version 1.0 * @date 2021-04 * @project JavaInterview * @package java_one * @desc 2.单例设计模式 * 懒汉式 - 线程安全,适用于多线程 */ public class Singleton5 { /** 为了避免初始化操作的指令重排序,给 instance 加上了 volatile */ private static volatile Singleton5 instance; private Singleton5() { } public static Singleton5 getInstance() { if (instance == null) { synchronized(Singleton5.class) { if (instance == null) { // ... try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } instance = new Singleton5(); } } } return instance; } }
测试代码:
class Singleton5Test { public static void main(String[] args) throws ExecutionException, InterruptedException { Callable<Singleton5> callable = Singleton5::getInstance; ExecutorService executorService = Executors.newFixedThreadPool(2); Future<Singleton5> future1 = executorService.submit(callable); Future<Singleton5> future2 = executorService.submit(callable); Singleton5 s1 = future1.get(); Singleton5 s2 = future2.get(); System.out.println(s1 == s2); System.out.println(s1); System.out.println(s2); executorService.shutdown(); } }
实现如下:
package java_one; /** * @author parzulpan * @version 1.0 * @date 2021-04 * @project JavaInterview * @package java_one * @desc 2.单例设计模式 * 懒汉式 - 静态内部类,线程安全,适用于多线程 * 当内部类被加载和初始化时,才会创建实例对象 */ public class Singleton6 { private Singleton6() {} private static class Inner { private static final Singleton6 INSTANCE = new Singleton6(); } public static Singleton6 getInstance() { return Inner.INSTANCE; } }
测试代码:
class Singleton6Test { public static void main(String[] args) throws ExecutionException, InterruptedException { Callable<Singleton6> callable = Singleton6::getInstance; ExecutorService executorService = Executors.newFixedThreadPool(2); Future<Singleton6> future1 = executorService.submit(callable); Future<Singleton6> future2 = executorService.submit(callable); Singleton6 s1 = future1.get(); Singleton6 s2 = future2.get(); System.out.println(s1 == s2); System.out.println(s1); System.out.println(s2); executorService.shutdown(); } }
总结:
推荐阅读:
如下代码的运算结果:
public class Father { private int i = test(); private static int j = method(); static { System.out.print("(1)"); } Father() { System.out.print("(2)"); } { System.out.print("(3)"); } public int test() { System.out.print("(4)"); return 1; } public static int method() { System.out.print("(5)"); return 1; } } public class Son extends Father{ private int i = test(); private static int j = method(); static { System.out.print("(6)"); } Son() { // super(); 写不写都存在,在子类构造器中一定会调用父类的构造器 System.out.print("(7)"); } { System.out.print("(8)"); } @Override public int test() { System.out.print("(9)"); return 1; } public static int method() { System.out.print("(10)"); return 1; } } package java_one.three; /** * @author parzulpan * @version 1.0 * @date 2021-04 * @project JavaInterview * @package java_one.three * @desc 3. 类初始化和实例初始化 */ public class Test { public static void main(String[] args) { // 正确输出 5 1 10 6 9 3 2 9 8 7 Son s1 = new Son(); System.out.println(); // 正确输出 9 3 2 9 8 7 Son s2 = new Son(); } }
总结:
<clinit>()
方法
<clinit>()
方法由静态类变量显示赋值代码和静态代码块组成<clinit>()
方法只执行一次<init>()
方法
<init>()
方法可能重载由多个,有几个构造器就有几个 <init>()
方法<init>()
方法由非静态类变量显示赋值代码和非静态代码块和对应构造器代码组成<init>()
方法的首行是 super() 或 super(实参列表) ,即对应父类的 <init>()
方法。它写不写都存在,在子类构造器中一定会调用父类的构造器推荐阅读:
"<clinit>"
"<init>"
"invokespecial 指令"
如下代码的运算结果:
package java_one.four; import java.util.Arrays; /** * @author parzulpan * @version 1.0 * @date 2021-04 * @project JavaInterview * @package java_one.four * @desc 4. 方法的参数传递机制 * i = 1 * str = hello * num = 2 * arr = [2, 2, 3, 4, 5] * myData.a = 11 */ public class ParameterPassing { public static void main(String[] args) { int i = 1; String str = "hello"; Integer num = 2; int[] arr = {1, 2, 3, 4, 5}; MyData myData = new MyData(); change(i, str, num, arr, myData); 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("myData.a = " + myData.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; }
总结:
推荐阅读:
有 n 步台阶,一次只能上 1 步或 2 步,共有多少种走法?
package java_one.five; /** * @author parzulpan * @version 1.0 * @date 2021-04 * @project JavaInterview * @package java_one.five * @desc 5. 递归和迭代 */ public class Fibonacci { private final int CONSTANT = 1000000007; public int numWaysByRecursion(int n) { if (n < 3) { return n; } return (numWaysByRecursion(n - 1) % CONSTANT + numWaysByRecursion(n - 2) % CONSTANT) % CONSTANT; } public int numWaysByIteration(int n) { int first = 0, second = 1, sum; for (int i = 0; i < n; ++i) { sum = (first + second) % CONSTANT; first = second; second = sum; } return second; } public static void main(String[] args) { Fibonacci fibonacci = new Fibonacci(); System.out.println(fibonacci.numWaysByRecursion(0)); System.out.println(fibonacci.numWaysByRecursion(1)); System.out.println(fibonacci.numWaysByRecursion(2)); System.out.println(fibonacci.numWaysByRecursion(10)); System.out.println(); System.out.println(fibonacci.numWaysByIteration(0)); System.out.println(fibonacci.numWaysByIteration(1)); System.out.println(fibonacci.numWaysByIteration(2)); System.out.println(fibonacci.numWaysByIteration(10)); } }
总结:
推荐阅读:
如下代码的运算结果:
package java_one.six; /** * @author parzulpan * @version 1.0 * @date 2021-04 * @project JavaInterview * @package java_one.six * @desc 6. 成员变量和局部变量 * 抓住: * 局部变量存在栈中,它每次调用都是新的生命周期 * 实例变量存在堆中,它随着对象的创建而初始化,随着对象的回收而消亡,每一个对象的实例变量是独立的 * 类变量存在方法区中,它随着类的初始化而初始化,随着类的卸载而消亡,该类的所有对象的类变量是共享的 */ public class MembersLocalVariables { static int s; int i; int j; { int i = 1; i++; j++; s++; } public void test(int j) { j++; i++; s++; } public static void main(String[] args) { MembersLocalVariables m1 = new MembersLocalVariables(); MembersLocalVariables m2 = new MembersLocalVariables(); m1.test(10); m1.test(20); m2.test(30); // 2 1 5 System.out.println(m1.i + " " + m1.j + " " + m1.s); // 1 1 5 System.out.println(m2.i + " " + m2.j + " " + m2.s); } }
总结:
局部变量与成员变量的区别
区别项 | 局部变量 | 成员变量 |
---|---|---|
声明位置 | 方法形参或内部、代码块类、构造器内等 | 类中方法外,其中有 static 修饰的称为类变量,没有 static 修饰的称为实例变量 |
修饰符 | 不能用权限修饰符修饰,可以用 final 修饰 | public、protected、private、final、static、volatile、transient |
初始化值 | 没有默认初始化值,必须显式赋值,方可使用;特别的,形参在调用时赋值 | 有默认初始化值,同数组类似 |
内存加载位置 | 栈中 | 类变量在方法区中,实例变量在堆中 |
作用域 | 从声明处开始,到所属的大括号结束 | 对于类变量:在当前类中“类名.” ,在其他类中“类名.” 或“对象名.” ;对于实例变量:在当前类中“this.” ,在其他类中“对象名.” |
生命周期 | 它每次调用都是新的生命周期 | 对于类变量:它随着类的初始化而初始化,随着类的卸载而消亡,该类的所有对象的类变量是共享的;对于实例变量:它随着对象的创建而初始化,随着对象的回收而消亡,每一个对象的实例变量是独立的 |
如何区分同名局部变量和成员变量
“this.”
“类名.”
推荐阅读:
Spring Bean 有五个作用域,比较基础的有:
如果是 Web 容器,还支持:
Spring Bean 的生命周期分为创建和销毁两个过程:
创建:
销毁:
总结:
推荐阅读:
事务的传播行为:
使用:@Transactional(propagation = Propagation.REQUIRED)
REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般用于增删改操作
SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。一般用于查操作
MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常
REQUERS_NEW 新建事务,如果当前在事务中,把当前事务挂起
NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
NEVER 以非事务方式运行,如果当前存在事务,抛出异常
NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作
事务的隔离级别:
TRANSACTION_READ_UNCOMMITTED
读未提交:允许事务读取未被其他事务提交的变更,出现 脏读、不可重复读、幻读等问题。TRANSACTION_READ_COMMITTED
读已提交:只允许事务读取已经被其他事务提交的变更,避免 脏读问题,出现 不可重复读、幻读等问题。这是 Oracle 默认的事务隔离级别TRANSACTION_REPEATABLE_READ
可重复读:确保在同一个事务中多次读取同样记录的结果是一致的,避免 脏读、不可重复读问题,出现 幻读等问题。这是 MySQL 默认的事务隔离级别。TRANSACTION_SERIALIZABLE
串行化:确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表进行增删改操作,避免上面所有问题。总结:
推荐阅读:
对于 Post 请求(form 标签 method=post
):解决的方法是在 web.xml
中配置一个编码过滤器
<web-app> <!-- 配置解决中文乱码的过滤器 --> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <!-- 设置过滤器中的属性值 --> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <!-- 过滤所有请求 --> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
对于 Get 请求:解决的方法是修改 Tomcat 的 server.xml
配置文件,添加 <Connector URIEncoding="UTF-8" useBodyEncodingForURI="true"/>
推荐阅读:
总结:
参考阅读:
例如:
属性名:实体类 id name password
字段名:数据库 id name pwd
mybatis 会根据数据库的字段名去找对应的实体类的属性名,它会将所有列名转换为小写,然后去找实体类中对应的 set 方法 ,set 方法后面的字段就对应数据库的字段名;如果不一样就会返回 null。
基本上有三种方式解决:
对于 CentOS6:
service 服务名 start
service 服务名 stop
service 服务名 restart
service 服务名 reload
service 服务名 status
/etc/init.d/服务名
chkconfig --list|grep xxx
chkconfig
命令设置自启动
chkconfig --level 5 服务名 on/off
对于 CentOS7:
systemctl start 服务名(xxxx.service)
systemctl restart 服务名(xxxx.service)
systemctl stop 服务名(xxxx.service)
systemctl reload 服务名(xxxx.service)
systemctl status 服务名(xxxx.service)
/usr/lib/systemd/system
systemctl list-unit-files
systemctl --type service
systemctl
命令设置自启动
systemctl enable/disable 服务名
查看分支:
# 查看本地分支 $ git branch # 查看远程分支 $ git branch -r # 查看本地、服务器所有分支 $ git branch -a # 显示本地分支和服务器分支的映射关系 $ git branch -vv
创建分支
# 创建本地分支,新分支创建后不会自动切换为当前分支 $ git branch [branch name]
创建分支后切换到新分支
# 建立分支后切换到新分支 $ git checkout -b [branch name]
切换到指定分支
# 切换到指定分支 $ git checkout [branch name]
本地分支关联到远程分支
# 本地分支建立,与远程分支同步之后,就可以直接使用 git pull 命令了 $ git branch --set-upstream-to=origin/<远端branch_name> <本地branch_name> # 举例 将本地 dev 分支关联到远程 dev 分支 $ git branch --set-upstream-to=origin/dev dev
合并分支
# 合并分支,将名称为[name]的分支与当前分支合并 $ git merge [name]
删除分支
# 删除远程分支 $ git push origin --delete [branch name] # 删除本地分支(-d 删除已经参与了合并的分支,对于未有合并的分支是无法删除的,如果想强制删除一个分支,可以使用 -D 选项) $ git branch -d [branch name]
显示分支和提交
# 显示分支和提交记录 $ git show-branch
RDB 和 AOF 的优缺点,以及使用建议。
总结:
推荐阅读:
总结:
推荐阅读:
推荐阅读:
总结:
单点登录:分布式系统中,一处登录多处使用。
至少需要考虑以下两个问题: