先看下代码
public class Test {
public static void main(String[] args) {
int i =1;
i = i++;
System.out.println("i1="+i);
System.out.println("------------");
int j = i++;
System.out.println("i2="+i);
System.out.println("j1="+j);
System.out.println("------------");
int k = i+ ++i * i++;
System.out.println("i="+i);
System.out.println("j="+j);
System.out.println("k="+k);
}
}
最终打印会是什么样子呢?先看下运行结果
(1)这里i1=1是因为i++中i=1先进入操作数栈
然后在局部变量表中i再自增1变为2,但这时经过‘=’操作后操作数栈中的1又赋给了局部变量表中的i(把原来的2覆盖掉了所以最终的值为1)
(2)这里的 i2=2 是因为原来i=1进去操作数栈后,自增1变为2后。并未进行 ‘i=’ 操作,而是开辟一个新的变量j,所以i为2,因为 j=‘i++’ 原来在操作数栈中的1又赋给了 j 所以j=1.
(3)这里i=4,j=1,k=11 是因为i=2 先进入操作数栈,++i 先自增1 变为3,再进去操作数栈
这时i++ 也进入栈然后自增1变为4 ,然后做乘法运算变为9 后放入操作数栈,最后进行
加法运算(这里是和原操作数栈中的2做加法运算)变成11,赋给了k,此时k=11 i=4 j=1…
饿汉式
方法1
饿汉式,直接创建对象,不管你是否需要这个对象,都会创建,步骤如下。
1.构造器私有化
2.自行创建,并且用静态变量保存
3.向外提供这个实例
4.强调这是个单例,可以用final修改
public class Singleton1 {
public final static Singleton1 SINSTANCE = new Singleton1();
private Singleton1()
{
}
}
方法2
枚举类型,表示该类型的对象是有限的几个
我们可以限定为一个,就成单例了。
public enum Singleton2 {
INSTANC12s
}
方法3
配置一个single.properties用于成员变量的初始化
配置格式如下:
public class Singleton3 {
@Override
public String toString() {
return "Singleton3 [info=" + info + "]";
}
public final static Singleton3 SINSTANCE;
private String info;
private Singleton3(String info)
{
this.info = info;
}
static {
try {
Properties pro = new Properties();
pro.load(Singleton3.class.getClassLoader().getResourceAsStream("single.properties"));
SINSTANCE = new Singleton3(pro.getProperty("info"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
懒汉式
创建步骤如下:
1.构造器私有化
2.用一个静态变量保存这个唯一的实例
3.提供一个静态方法,获取这个实例对象
方法1
public class Singleton4 {
private static Singleton4 instance;
private Singleton4() {
}
public static Singleton4 getInstance() {
if(instance == null) {
synchronized(Singleton4.class){
if(instance == null) {
instance = new Singleton4();
}
}
}
return instance;
}
}
方法2
以下是内部类形式创建
既能保证线程安全,也能延迟加载在内部类被加载和初始化时,才创建对象。.静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独加载和初始化的。因为是在内部类加载和初始化时,创建的,因此是线程安全的。
public class Singleton5 {
private Singleton5() {
}
private static class Inner{
private static final Singleton5 INSTANCE = new Singleton5();
}
public static Singleton5 getInstance() {
return Inner.INSTANCE;
}
}
请问下列运行结果是什么?
/**
* 父类的初始化
* 1.j=method();
* 2.父类的静态代码块
* @author qiu
* 父类的实例初始化
* 1.super()
* 2.i = test()
* 3.父类的非静态代码块
* 4.父类的无参构造(最后)
*
* 非静态方法前面其实有一个默认的对象this
* this在构造器(或)它表示的是正在创建的对象,因为这里创建的是son()对象,所以
* test()指的是子类重写的代码(面向对象多态)
*
* 这里i=test()执行的是子类重写的test()方法
*
*/
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;
}
}
/**
* 子类的初始化
* 1.j=method();
* 2.子类的静态代码块
*
* 先初始化父类 (5) (1)
* 初始化子类 (10) (6)
* @author qiu
* 子类的实例初始化
* 1.super()
* 2.i = test()
* 3.子类的非静态代码块 //顺序执行
* 4.子类的无参构造(最后)
*
* 哪些方法不可以被重写
* 1.final
* 2.静态方法
* 3.private等子类中不可见方法
*
* 对象的多态性
* 1.子类如果中写了父类的方法,通过子类对象调用的一定是子类重写过的代码
* 2.非静态方法默认的调用对象是this
* 3.this对象在构造器或者说方法中就是正在创建的对象
*
*/
public class Son extends Father {
private static int j = method();
private int i = test();
static {
System.out.print("(6)");
}
Son(){
super();//写不写都行,在子类构造器中一定会调用父类的构造器。
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) {
//类初始化、实例初始化(实例初始化与类初始化不同,它可能有多个,new几次就有几个 )
Son s = new Son();
System.out.println();
Son s1 = new Son();
}
}
1.形参是基本数据类型
传递数据值
2.实参是引用数据类型
传递数据地址
特殊类型:String、包装类等对象不可变性
import java.util.Arrays;
public class Test1 {
public static void main(String[] args) {
int i = 1;
String str = "hello";
Integer num = 200;
int[] arr = {1,2,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;
}
编程题:有n步台阶,一次只能上1步或2步,共有多少种走法?
思想:
public class Step {
public static int f(int n) {
if(n==1 || n==2) {
return n;
}
return f(n-2)+f(n-1);
}
public static void main(String[] args) {
System.out.println(f(4));
}
}
package demo4;
public class Test2 {
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) {
Test2 obj1 = new Test2();
Test2 obj2 = new Test2();
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);
}
}
1.局部变量与成员变量的区别
(1)声明的位置
局部变量: 方法体{} 中,形参,代码块{}中
成员变量: 类中方法外
1. 类变量: 有static修饰
2.实例变量: 没有static修饰
(2)修饰符
局部变量:final
成员变量:public、protected、private、final、static等
(3)值存储的位置
局部变量:栈
实例变量:堆
类变量:方法区
(4)作用域
局部变量:从声明处开始,到所属的}结束
实例变量:在当前类中“this.”(有时this.可以省略),在其他类中“对象名."访问
类变量:在当前类中“this.”(有时this.可以省略),在其他类中“类名.”或“对象名."访问
(5)生命周期
局部变量:每一次线程,每一次调用执行都是新的生命周期
实例变量: 随着对象的创建而初始化,随着对象的被回收而消亡,每一个对象的实例变量都是独立的
类变量:随着类的初始化而初始化,随着类的卸载而消亡,该类的所有对象的类的变量是共享的
运行结果如下:
在main函数中下面两行代码运行效果如下:
Test2 obj1 = new Test2();
Test2 obj2 = new Test2();
剩下几行运行效果如下
总结
当局部变量与XX变量重名时,如何区别?
1.当局部变量与实例变量重名
在实例变量前加“this.”
2.当局部变量与类变量重名时
在类变量前加“类名.”
该经典面试题出自此处
我只是它的搬运工,个人感觉讲的比细致,比较好吧.