问题和知识点
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);
}
运行结果如下:
i=4
j=1
k=11
说明:
赋值=,最后计算
=右边的从左到右加载值一次压入操作数栈
实际先算哪个,看运算符优先级
自增、自减操作都是直接修改变量的值,不经过操作数栈
最后的赋值之前,临时结果也是存储在操作数栈中
2.什么是单例设计模式?常见的有哪几种形式?
单例设计模式,即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。
构造要点:
1.是某个类只能有一个实例;
构造器私有化
2.是它必须自行创建这个实例;
含有一个该类的静态变量来保存这个唯一的实例
3.是它必须自行向整个系统提供这个实例;
对外提供获取该实例对象的方式:
(1)直接暴露(2)用静态变量的get方法获取
常见的几种形式
1.饿汉式:直接创建对象,不存在线程安全问题
直接实例化饿汉式(简洁直观)
public class Singleton1 {
public static final Singleton1 INSTANCE=new Singleton1();
//final修饰非强制性的
private Singleton1() {
}
}
枚举式(最简洁)
public enum Singleton2 {
INSTANCE
}
静态代码块饿汉式(适合复杂实例化)
public class Singleton3 {
private Singleton3() {}
public static final Singleton3 INSTANCE;
static {
INSTANCE=new Singleton3();
}
}
简单的修改:
public class Singleton3 {
public static final Singleton3 INSTANCE;
private String info;
static {
try {
Properties pro = new Properties();
pro.load(Singleton3.class.getClassLoader().getResourceAsStream("single.properties"));
INSTANCE = new Singleton3(pro.getProperty("info"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private Singleton3(String info) {}
}
2.懒汉式:延迟创建对象
线程不安全(适用于单线程)
线程安全(适用于多线程)
public class Singleton4 {
private Singleton4() {}
private static Singleton4 instance;
public static Singleton4 getInstance() {
if(instance==null) {
synchronized(Singleton4.class) {
if(instance==null) {
instance=new Singleton4();
}
}
}
return instance;
}
}
静态内部类形式(适用于多线程)
/* 在内部类被加载和初始化时,才创建INSTANEC实例对象
* 静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的
* 因为实在内部类加载和初始化的,创建的,因此是线程安全的
* */
public class Singleton5 {
private Singleton5() {
}
private static class Inner{
private static final Singleton5 INSTANCE=new Singleton5();
}
public static Singleton5 getInstance() {
return Inner.INSTANCE;
}
}
3.
类初始化过程:
1.一个类要创建实例需要先加载并初始化该类
1)main方法所在的类需要先加载和初始化
2.一个子类要初始化需要先初始化父类
3.一个类初始化就是执行<clinit>
()方法
1)<clinit>
()方法由静态类变量显示赋值代码和静态代码块组成
2)类变量显示赋值代码和静态代码块代码从上到下顺序执行‘
3)<clinit>
()方法只执行一次
实例初始化过程
1.实例初始化就是执行<init>
()方法
1)<init>
()方法可能重载有多个,有几个构造器就有几个方法
2)<init>
()方法由非静态实例变量显示赋值代码和非静态代码块、对应构造器代码组成
3)非静态实例变量显示赋值代码和非静态代码块代码从上到下顺序执行,而对应构造器的代码最后执行
4)每次创建实例对象,调用对应构造器,执行的就是对应的方法
5)<init>
方法的首行是super()或super(实参列表),即对应父类的<init>
方法
子类实例化过程(假设类成员方法或者变量已经实现)
1.super(参数列表)
2.顺序执行实例赋值和者代码块
3.子类的构造器
父类实例化的过程:
(1)super(参数列表)(最前)
(2)顺序执行实例赋值和者代码块
(3)父类的构造器
4.哪些方法不可以被重写?
final方法
静态方法
private等子类中不可见方法
5.对象的多态性
1)子类如果重写了父类中的方法,通过子类对象调用的一定是子类重写的代码
2)非静态方法默认的调用对象是this
3)this对象在构造器后者说方法中就是正在被创建的对象
6.查看如下代码运行结果
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 static void main(String[] args) {
}
}
结果:
(5)(1)
代码1去掉main方法,再测试代码2
public class Son extends Father{
private int i=test();
private static int j=method();
static {
System.out.print("(6)");
}
Son(){
System.out.print("(7)");
}
{
System.out.print("(8)");
}
public int test() {
System.out.print("(9)");
return 1;
}
public static int method() {
System.out.print("(10)");
return 1;
}
public static void main(String[] args) {
}
}
运行结果如下:
(5)(1)(10)(6)
修改代码2给如下代码:
public class Son extends Father{
private int i=test();
private static int j=method();
static {
System.out.print("(6)");
}
Son(){
System.out.print("(7)");
}
{
System.out.print("(8)");
}
public int test() {
System.out.print("(9)");
return 1;
}
public static int method() {
System.out.print("(10)");
return 1;
}
public static void main(String[] args) {
Son s1=new Son();
System.out.println();
Son s2=new Son();
}
}
运行结果为:
(5)(1)(10)(6)(9)(3)(2)(9)(8)(7)
(9)(3)(2)(9)(8)(7)
7.查看如下代码运行结果
public class Exam4 {
public static void main(String[] args) {
int i = 1;
String str = "hello";
Integer num = 2;
int[] arr = {1,2,3,4,5};
MyData my = new MyData();
change(i,str,num,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;
}
结果为:
i = 1
str = hello
num = 2
arr = [2, 2, 3, 4, 5]
my.a = 11
方法的传递机制:
1.形参是基本数据类型
传递数据值
2.实参是引用数据类型
传递地址值
特殊的类型:String、包装类等对象不可变性
8.有n步台阶,一次只能上1步或2步,共有多少种走法?
解析步骤
代码如下:
public int f(int n) {
if(n==1|n==2) {
return n;
}
return f(n-2)+f(n-1);
}
解析方式2
代码如下:
public int loop(int n) {
if(n==1|n==2) {
return n;
}
int one=2;
int two=1;
int sum=0;
for(int i=3;i<=n;i++) {
sum=two+one;
two=one;
one=sum;
}
return sum;
}
9.局部变量与成员变量的区别
10.查看如下代码运行结果
public class Exam5 {
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) {
Exam5 obj1=new Exam5();
Exam5 obj2=new Exam5();
obj1.test(10);
obj1.test(20);
obj2.test(30);
System.out.println(obj1.i+","+obj1.j+","+obj1.s);
System.out.println(obj2.i+","+obj2.j+","+obj2.s);
}
}
运行结果如下:
2,1,5
1,1,5