飞道的博客

JavaSE基础经典面试题(找工作必看)

274人阅读  评论(0)

1.自增变量

先看下代码

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

2.单例设计模式

饿汉式

方法1

/**
 * 饿汉式,直接创建对象,不管你是否需要这个对象,都会创建。
 * 1.构造器私有化
 * 2.自行创建,并且用静态变量保存
 * 3.向外提供这个实例
 * 4.强调这是个单例,可以用final修改
 * @author qiu
 *
 */
public class Singleton1 {
 public final  static Singleton1 SINSTANCE = new Singleton1();
 private Singleton1()
	{
	  
    }
	
}

方法2

/**
 * 枚举类型,表示该类型的对象是有限的几个
 * 我们可以限定为一个,就成单例了。
 * @author qiu
 *
 */
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

/**
 * 1.构造器私有化
 * 2.用一个静态变量保存这个唯一的实例
 * 3.提供一个静态方法,获取这个实例对象
 * @author qiu
 *
 */
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

/**
 * 既能保证线程安全,也能延迟加载
 * 在内部类被加载和初始化时,才创建对象。
 * 静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独加载和初始化的。
 * 因为是在内部类加载和初始化时,创建的,因此是线程安全的。
 * @author qiu
 *
 */
public class Singleton5 {
	private Singleton5() {
		
		
	}
	private static class Inner{
	private static final Singleton5 INSTANCE = new Singleton5();
    
	}
	public static Singleton5 getInstance() {
		return Inner.INSTANCE;
	}
	
}

3.类的初始化和实例化

请问下列运行结果是什么?

/**
 * 父类的初始化<clinit>
 * 1.j=method();
 * 2.父类的静态代码块
 * @author qiu
 * 父类的实例初始化
 * 1.super()
 * 2.i = test()
 * 3.父类的非静态代码块
 * 4.父类的无参构造(最后)
 * 
 * 非静态方法前面其实有一个默认的对象this
 * this在构造器(或<init>)它表示的是正在创建的对象,因为这里创建的是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;
}

}
/**
 * 子类的初始化<clinit> 
 * 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对象在构造器或者说<init>方法中就是正在创建的对象
 * 
 */
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();
	}

}

打印结果如下

4.方法参数传递机制

import java.util.Arrays;
/**
 * 1.形参是基本数据类型
 * 传递数据值
 * 2.实参是引用数据类型
 * 传递数据地址
 * 特殊类型:String、包装类等对象不可变性
 * 
 * @author qiu
 *
 */
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;
}

运行结果如下

5.递归与迭代

编程题:有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));
		
		
	}

}

6.成员变量与局部变量

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.当局部变量与类变量重名时
在类变量前加“类名.”

该经典面试题出自此处
我只是它的搬运工,个人感觉讲的比较好吧.


转载:https://blog.csdn.net/qq_38790872/article/details/105455965
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场