企业真题

静态变量和实例变量的区别?

来源:保?丰、?软国际、?软华?、北京明??信、上海?动

静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?

来源:?度、Vi?o

  • 静态属性和静态方法可以被继承
  • 静态方法不能被重写。不存在多态性。

是否可以从一个 static 方法内部发出对非 static 方法的调用?

来源:同?顺、浩?科技

不行!只能通过对象来对非静态方法的调用。

static 修饰的成员(类、方法、成员变量)能否再使用 private 进行修饰?

来源:联?优势

完全可以。除了代码块。

知道哪些设计模式?

来源:?通快递、蚂??服

经典的:23 种

单例模式、模板方法、享元设计模式

开发中都用到了那些设计模式?用在什么场合?

来源:久?国际物流

main() 方法的 public 能不能换成 private,为什么

来源:凡?科技、顺?

可以改。但是改完以后就不是程序入口了。

Java 中类的变量初始化的顺序?

来源:航?拓普、?壳

实例变量赋值顺序

静态代码块,普通代码块,构造方法,从类加载开始的执行顺序?

来源:恒?电子、?科软、软??力、同?顺

  1. 静态代码块
  2. 普通代码块
  3. 构造器

1. 描述一下对 final 理解

来源:华??博普

  1. 修饰类
  2. 修饰方法
  3. 修饰变量

使用 final 修饰一个变量时,是引用不能改变,引用指向的对象可以改变?

来源:?米

引用不能改变。

引用指向的对象实体中的属性,如果没有使用 final 修饰,则可以改变。

final 能不能用于修饰构造方法?

来源:联?优势

final 不能修饰构造方法

finalstatic final 修饰成员变量,能不能进行 ++ 操作?

来源:佳?贸易

不能。

什么是抽象类?如何识别一个抽象类?

来源:易?支付

使用 abstract 修饰。

为什么不能用 abstract 修饰属性、私有方法、构造器、静态方法、final 的方法?

来源:止??善

为了语言的自洽。

接口与抽象类的区别?

来源:字?跳动、阿?校招、?度校招、??计算机技术及应用研究所、航?拓普、纬?、招??晟、汇?云通、数信??科技、北京永?鼎力、上海?连科技

接口与抽象类之间的对比

接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承实现类(concrete class)?

来源:航?拓普、?蝶、深圳德?科技、久?国际物流

是;是;是;

接口可以有自己属性吗?

来源:华?中盛

可以。必须是 public static final

如何访问接口的默认方法

来源:上海?思

使用实现类的对象进行调用。而且实现还可以重写此默认方法。

内部类有哪几种?

来源:华油??普、来?科技

内部类

2. 使用过内部类编程吗,有什么作用

来源:招通??、北京楚?龙、软??力、阿?校招、上海立?网络

内部类

枚举可以继承吗?

来源:顺?

使用 enum 定义的,其父类就是 Enum 类,就不能再继承其他的类了。

Java 基本类型与包装类的区别

来源:凡?科技

略。

谈谈你对面向对象的理解

来源:君?科技、航?拓普

  • 面向对象的两个要素:类、对象 面向对象编程。“万事万物皆对象”。
  • 面向对象的三大特征
  • 接口,与类并列的结构,作为一个补充:类可以实现多个接口。

面向对象的特征有哪些方面? (

来源:北京楚?龙、深圳德?科技、直?科技、米?奇网络、航?拓普、平??服

封装、继承、多态、抽象

拓展练习

“遮蔽”、++

考核点:类初始化,局部变量与类变量,自增自减

public class Exercise7 {
	static int x, y, z;
 
	static {
		int x = 5;
		x--;
	}
 
	static {
		x--;
	}
 
	public static void main(String[] args) {
		System.out.println("x=" + x);
		z--;
		method();
		System.out.println("result:" + (z + y + ++z));
	}
 
	public static void method() {
		y = z++ + ++z;
	}
}

static 成员变量

public class Exercise8 {
	public static void main(String[] args) {
		System.out.println(new SDText().x + "," + new SDText().y + "," + new SDText().x);
	}
}
 
class SDText {
	static SDText sd = new SDText();
	static int x = 3;
	static int y;
	public SDText() {
		x++;
		y++;
	}
}

static 成员变量:

  1. 什么时候创建?
  2. 共享(就一份)

类初始化流程

public class T {
	public static int k = 0;
	public static T t1 = new T("t1");
	public static T t2 = new T("t2");
	public static int i = print("i");
	public static int n = 99;
	
	public int j = print("j");
 
	{
		print("构造块");
	}
 
	static {
		print("静态块");
	}
 
	public T(String str) {
		System.out.println((++k) + ":" + str + "  i=" + i + "  n=" + n);
		++n;
		++i;
	}
 
	public static int print(String str) {
		System.out.println((++k) + ":" + str + "  i=" + i + "  n=" + n);
		++n;
		return ++i;
	}
 
	public static void main(String[] args) {}
}
就是完成类初始化
 
创建对象,调用类的实例初始化<init>() 或 <init>(String str)
 
1.静态变量的显式赋值
k = 0;
t1 = new T("t1");
	<init>(String str)
		① j = print("j");
		   // System.out.println...
		   ++k=1 : j i=0 n=0
           // ++n;
		   n=1
		   // return ++i;
		   i=1
           j=1
		② {print("构造块");}
		   // System.out.println...
		   ++k=2 : 构造块 i=1 n=1
		   // ++n;
		   n=2
		   // return ++i;
		   i=2
public T(String str)
		   // System.out.println...
		   ++k=3 : t1 i=2 n=2
		   // ++n;
		   n=3
		   // ++i;
		   i=3
 
t2 = new T("t2");
	<init>(String str)
		① j = print("j");
		   // System.out.println...
		   ++k=4 : j i=3 n=3
           // ++n;
		   n=4
		   // return ++i;
		   i=4
           j=4
		② {print("构造块");}
		   // System.out.println...
		   ++k=5 : 构造块 i=4 n=4
           // ++n;
		   n=5
		   // return ++i;
		   i=5
public T(String str)
		   // System.out.println...
		   ++k=6 : t2 i=5 n=5
		   // ++n;
		   n=6
		   // ++i;
		   i=6
 
i = print("i");
	// System.out.println...
    ++k=7 : i i=6 n=6
    // ++n;
    n=7
    // return ++i;
    ++i=7
    i=7
 
n = 99;
 
2. 静态代码块
static {print("静态块");}
	// System.out.println...
    ++k=8 : 静态块 i=7 n=99
    // ++n;
    n=100
    // return ++i;
    i=8

类初始化与实例初始化 1

class HelloA {
	public HelloA() {
		System.out.println("HelloA");
	}
 
	{
		System.out.println("I'm A Class");
	}
 
	static {
		System.out.println("static A");
	}
}
 
public class HelloB extends HelloA {
	public HelloB() {
		System.out.println("HelloB");
	}
 
	{
		System.out.println("I'm B Class");
	}
 
	static {
		System.out.println("static B");
	}
 
	public static void main(String[] args) {
		new HelloB();
	}
}
父类 HelloA 装载:
System.out.println("static A");
 
子类 HelloB 装载:
System.out.println("static B");
 
new HelloB():对象创建
1. 父类 HelloA <init>()
代码块:System.out.println("I'm A Class");
构造器:System.out.println("HelloA");
 
2. 子类 HelloB <init>()
System.out.println("I'm B Class");
System.out.println("HelloB");

实例初始化与函数重写

public class Exercise13 {
	public static void main(String[] args) {
		Sub s = new Sub();
	}
}
 
class Base {
	Base() {
		method(100);
	}
 
	{
		System.out.println("base");
	}
 
	public void method(int i) {
		System.out.println("base : " + i);
	}
}
 
class Sub extends Base {
	Sub() {
		super.method(70);
	}
 
	{
		System.out.println("sub");
	}
 
	public void method(int j) {
		System.out.println("sub : " + j);
	}
}
对象创建:
1. 父对象:Base<init>()
	1. 代码块:base
	2. method(100):创建的是子类,调用子类重写的方法:sub : 100
		这里看创建的哪个类,是看运行时类型,即:new Sub();
		而不是看编译是类型:Sub s = 
		所以即使这里改成:Base s = new Sub(),依然调 Sub 重写的方法
1. 子对象:Sub<init>()
	1. 代码块:sub
	2. super.method(70):调父类方法:base : 70

类初始化与实例初始化 2

public class Exercise14 {
	public static void main(String[] args) {
		Son son = new Son();
	}
}
 
class Father {
	static {
		System.out.println("(1)父类的静态代码块");
	}
 
	{
		System.out.println("(2)父类的非静态代码块");
	}
 
	Father() {
		System.out.println("(3)父类的无参构造");
	}
}
 
class Son extends Father {
	static {
		System.out.println("(4)子类的静态代码块");
	}
 
	{
		System.out.println("(5)子类的非静态代码块");
	}
 
	Son() {
		System.out.println("(6)子类的无参构造");
	}
}
类装载:
父:(1)父类的静态代码块
子:(4)子类的静态代码块
 
对象创建:
<init>():
1. 代码块:(2)父类的非静态代码块
2. 构造器:(3)父类的无参构造
<init>():
1. 代码块:(5)子类的非静态代码块
2. 构造器:(6)子类的无参构造

静态方法不是重写,没有多态

public class Exercise15 {
	public static void main(String[] args) {
		Zi zi = new Zi();
	}
}
 
class Fu {
	private static int i = getNum("(1)i");
	private int j = getNum("(2)j");
 
	static {
		print("(3)父类静态代码块");
	}
 
	{
		print("(4)父类非静态代码块,又称为构造代码块");
	}
 
	Fu() {
		print("(5)父类构造器");
	}
 
	public static void print(String str) {
		System.out.println(str + "->" + i);
	}
 
	public static int getNum(String str) {
		print(str);
		return ++i;
	}
}
 
class Zi extends Fu {
	private static int k = getNum("(6)k");
	private int h = getNum("(7)h");
 
	static {
		print("(8)子类静态代码块");
	}
 
	{
		print("(9)子类非静态代码块,又称为构造代码块");
	}
 
	Zi() {
		print("(10)子类构造器");
	}
 
	public static void print(String str) {
		System.out.println(str + "->" + k);
	}
 
	public static int getNum(String str) {
		print(str);
		return ++k;
	}
}
类装载:
父:
private static int i = getNum("(1)i");
	print(str); // (1)i -> 0
	return ++i; // 即:i = ++i // i = 1
static {print("(3)父类静态代码块");}
	print(str); // (3)父类静态代码块 -> 1
 
子:
private static int k = getNum("(6)k");
	print(str); // (6)k -> 0
	return ++k; // 即:k = ++k // k = 1
static {print("(8)子类静态代码块");}
	print(str); // (8)子类静态代码块 -> 1
 
对象创建:Zi zi = new Zi();
<init>():
private int j = getNum("(2)j");
	print(str); // (2)j -> 1
	return ++i; // i = 2, j = 2
{print("(4)父类非静态代码块,又称为构造代码块");}
	print(str); // (4)父类非静态代码块,又称为构造代码块 -> 2
Fu() {print("(5)父类构造器");}
	print(str); // (5)父类构造器 -> 2
 
 
<init>():
private int h = getNum("(7)h");
	print(str); // (7)h -> 1
	return ++k; // k = 2, h = 2
{print("(9)子类非静态代码块,又称为构造代码块");}
	print(str); // (9)子类非静态代码块,又称为构造代码块 -> 2
Zi() {print("(10)子类构造器");}
	print(str); // (10)子类构造器 -> 2

调用运行时类型的重写方法 1

public class Exercise16 {
    public static void main(String[] args) {
        Son s1 = new Son();
    }
}
 
class Father {
    private int a = getNumber();
 
    {
        System.out.println("Father非静态代码块 a = " + a);
    }
 
    Father() {
        System.out.println("Father()无参构造");
    }
 
    public int getNumber() {
        System.out.println("Father:getNumber()");
        return 1;
    }
}
 
class Son extends Father {
    {
        System.out.println("Son非静态代码");
    }
 
    public Son() {
        System.out.println("Son():无参构造");
    }
 
    public int getNumber() {
        System.out.println("Son:getNumber()");
        return 2;
    }
}
父对象创建:
private int a = getNumber(); // 创建的是 new Son(); 调 Son 重写的 getNumber() 方法
	// Son:getNumber()
	return 2; // a = 2
代码块:// Father非静态代码块 a = 2
构造函数:// Father()无参构造
 
子对象创建:
代码块:// Son非静态代码
构造函数:// Son():无参构造

调用运行时类型的重写方法 2

public class Exercise17 {
    public static void main(String[] args) {
        Base s = new Sub();
    }
}
 
class Base {
    Base() {
        this.method(100);
    }
 
    {
        System.out.println("base");
    }
 
    public void method(int i) {
        System.out.println("base : " + i);
    }
}
 
class Sub extends Base {
    Sub() {
        super.method(70);
    }
 
    {
        System.out.println("sub");
    }
 
    public void method(int j) {
        System.out.println("sub : " + j);
    }
}
父对象创建:
代码块:// base
构造函数:// sub : 100
// 运行时类型:new Sub();,调 Sub 重写的方法
// 和编译时类型 Base s = 无关
 
子对象创建:
代码块:// sub
构造函数:// base : 70
// 显式调的 super

final 修饰引用类型

public class TestOther {
    public static void main(String[] args) {
        Other o = new Other();
        new TestOther().addOne(o);
        /*
         (1)new TestOther():匿名对象,作用是为了调用 addOne 方法。
         (2)上面的实参 o,把 Other 对象的地址值,传给了下面的 addOne 方法的形参 o
         (3)下面的 addOne 方法的形参 o,前面有一个 final 修饰,
         这个 final 在这里的意思是,形参 o 不能够指向新的对象,
         这就意味着,形参和实参此时一定是指向同一个对象。
         (4)如果形参和实参指向同一个对象,那么形参对象属性值的修改,其实就是实参对象属性值的修改
         */
        System.out.println(o.i); // 1
    }
 
    public void addOne(final Other o){
        // o = new Other(); //错误,o 不能重新赋值
        o.i++; // 没改 o,o.i 不是 final,可以改
    }
}
 
class Other {
    public int i; // 如果 i 前面有 final,才是表示 i 的值不能被修改
}

属性冲突

interface A {
	int x = 0;
}
 
class B {
	int x = 1;
}
 
public class C extends B implements A {
	public void printX() {
		System.out.println(x);
	}
 
	public static void main(String[] args) {
		new C().printX();
	}
}

默认方法冲突 1

类优先原则

“默认”的含义:没有就用我默认的,有了就不用默认的了

interface A {
    default void print() {
        System.out.println("interface A");
    }
}
 
class B {
    public void print() {
        System.out.println("class B");
    }
}
 
public class C extends B implements A {
    public static void main(String[] args) {
        new C().print(); // class B
    }
}

默认方法冲突 2

interface A {
    default void print() {
        System.out.println("interface A");
    }
}
 
class B {
    public void print() {
        System.out.println("class B");
    }
}
 
public class C extends B implements A {
	public void print() {
		// 子类完全重写
        System.out.println("class C");
        // 调父类
        super.print();
        // 调接口默认方法
        A.super.print();
    }
 
    public static void main(String[] args) {
        new C().print();
    }
}

默认方法冲突 3

interface Playable {
    default void play() {
        System.out.println("Playable");
    }
}
 
interface Bounceable {
    default void play() {
        System.out.println("Bounceable");
    }
}
 
public class Ball implements Playable, Bounceable {
    public static void main(String[] args) {
        new Ball().play();
    }
}
Ball.java:13: error: types Playable and Bounceable are incompatible;
public class Ball implements Playable, Bounceable {
       ^
  class Ball inherits unrelated defaults for play() from types Playable and Bounceable
1 error

局部内部类

public class Exercise36 {
	public static void main(String[] args) {
        Out out = new Out();
        out.Print(3);
    }
}
 
class Out {
    private int age = 12;
 
    public void Print(final int x) {
        class In {
            public void inPrint() {
                System.out.println(x); // 3
                System.out.println(age); // 12
            }
        }
        new In().inPrint();
    }
}

同名变量访问

public class Exercise37 {
    public static void main(String[] args) {
        Out.In in = new Out().new In();
        in.print();
    }
}
 
class Out {
    private int age = 12;
 
    class In {
        private int age = 13;
        public void print() {
            int age = 14;
            System.out.println("局部变量:" + age); // 14
            System.out.println("内部类变量:" + this.age); // 13
            System.out.println("外部类变量:" + Out.this.age); // 12
        }
    }
}

static 内部类只能由对象 new

public class Exercise38 {
    public Exercise38() {
        Inner s1 = new Inner();
        s1.a = 10;
        Inner s2 = new Inner();
        s2.a = 20;
        Exercise38.Inner s3 = new Exercise38.Inner(); // 和上面是一样的,都是 this 调的
        System.out.println(s3.a);
    }
 
    class Inner {
        public int a = 5;
    }
 
    public static void main(String[] args) {
        Exercise38 t = new Exercise38();
        Inner r = t.new Inner();
        System.out.println(r.a);
    }
}

包装类缓存

public static void main(String[] args) {
    Integer i1 = 128;
    Integer i2 = 128;
    int i3 = 128;
    int i4 = 128;
    System.out.println(i1 == i2);
    System.out.println(i3 == i4);
    System.out.println(i1 == i3);
 
    double a = 2.0;
	double b = 2.0;
	Double c = 2.0;
	Double d = 2.0;
	System.out.println(a == b);
	System.out.println(c == d);
	System.out.println(a == d);
}
  • Integer 有 0~127 缓存
  • Double 无缓存