1. 基础

1. 重写

  • 重写发生在子类与父类之间
  • 方法的重写(override)两同两小一大原则:
    • 方法名相同,参数类型相同
    • 子类返回类型小于等于父类方法返回类型,
    • 子类抛出异常小于等于父类方法抛出异常,
    • 子类访问权限大于等于父类方法访问权限。
  • 运行时多态(动态多态)

2. 重载

  • 重载发生在同一个类里面
  • 方法名字相同,而参数不同
  • 如构造函数
  • 编译时多态(静态多态)

3. java静态变量、代码块、和静态方法的执行顺序

基本上代码块分为三种:Static静态代码块、构造代码块、普通代码块
代码块执行顺序: 静态代码块——> 构造代码块 ——> 构造函数——> 普通代码块
继承中代码块执行顺序: 父类静态块——>子类静态块——>父类代码块——>父类构造器——>子类 代码块——>子类构造器

4. 面向对象特点

  • 优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护。
  • 缺点:性能比面向过程低。

三大特性: 封装、继承、多态

5. 抽象类和接口的区别

A:成员的区别
抽象类:
构造方法:有构造方法,用于子类实例化使用。
成员变量:可以是变量,也可以是常量。
成员方法:可以是抽象的,也可以是非抽象的。

接口:
构造方法:没有构造方法
成员变量:只能是常量。默认修饰符:public static final
成员方法:jdk1.7只能是抽象的。默认修饰符:public abstract (推荐:默认修饰符请自己永远手动给出)
jdk1.8可以写以default和static开头的具体方法

6. 关于父类和子类的静态方法的继承或重写问题

父类

public class Father {

    public static void show() {
        System.out.println(" 父类的静态方法");
    }

    public static void method() {
        System.out.println("父类的method静态方法");
    }
}

子类

public class Son extends Father{

    public static void show() {
        System.out.println("子类的静态方法 ");
    }


    public static void main(String[] args) {

        Father father =  new Son();
        father.show();//是否重写父类静态方法,表现多态性


        Son son = new Son();
        son.show();
        son.method();//是否继承父类静态方法

    }
}

输出结果

父类的静态方法
子类的静态方法
父类的method静态方法

结论

不呈现多态性,
子类不会重写父类的静态方法
当子类和父类都有同一个名字的静态方法时,这两个方法是相互独立的,不存在重写
子类可以继承父类的静态属性和静态方法(父类的不为private)

7. 反射

反射的三种获取方法

  1. Class clazz = Class.forName(“com.zzt.Person”) //类的具体地址
  2. Class clazz = Person.class; //类名
  3. Class clazz = zhangsan.getClass(); //具体对象名

反射获取对象

  1. 获取类对象实例
Class clazz = Class.forName("com.zzt.Person")
  1. 根据类对象实例获取Constructor
Constructor personConstructor = clazz.getConstructor()
  1. 使用construction获取反射类对象
Object personObj = personConstructor.newInstance();
  1. 调用方法
    • 获取方法的Method对象
    Method setAgeMethod = clazz.getMethod("setAge",int.class);
    
    • 用invoke调用方法
    setAgeMethod.invoke(personObj,18)
    

8. 虚拟机三个步骤

装载、连接(验证、准备、解析)、初始化

9. 序列化

实现

实现Serializable接口或者Externalizable接口。
序列化接口没有方法或字段,仅用于标识可序列化的语义。


Serializable

public static void main(String[] args) throws IOException, ClassNotFoundException {
        Person person = new Person();
        person.setAge(18);
        person.setName("zhangsan");

        //序列化
        FileOutputStream fos = new FileOutputStream("tempFile");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(person);

        //反序列化
        File tempFile = new File("tempFile");
        FileInputStream fis = new FileInputStream(tempFile);
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object o = ois.readObject();
        System.out.println(o);   // Person{name='zhangsan', age=18}
    }

如果实现的是Externalizable接口,需要重写两个方法

	@Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(age);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        age = (Integer) in.readObject();
    }

测试类代码同上,但是返回结果
Person{name=‘null’, age=18}
只有age
所以,使用实现Externalizable接口可以自己决定要存储哪些信息(age),而name因为没有在重写代码中定义,所以即使set了,也存储不进去。

问题:

序列化中如果有些字段不想进行序列化

可以在变量前面添加transient关键字修饰。 transient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中。 在被反序列化后, transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。 transient 只能修饰变量,不能修饰类和方法。

静态变量会被序列化吗

不会。因为序列化是针对对象而言的, 而静态变量优先于对象存在, 随着类的加载而加载, 所以不会被序列化。

ps:
看到这个结论, 是不是有人会问, serialVersionUID也被static修饰, 为什么serialVersionUID会被序列化?
其实serialVersionUID属性并没有被序列化, JVM在序列化对象时会自动生成一个serialVersionUID, 然后将我们显示指定的serialVersionUID属性值赋给自动生成的serialVersionUID。


10. Error 和 Exception 区别

所有的异常都有一个共同的祖先 java.lang 包中的 Throwable 类。 Throwable 类有两个重要的子类 Exception (异常)和 Error (错误)。
Exception 和 Error 二者都是 Java 异常处理的重要子类,各自都包含大量子类。

  • Exception :程序本身可以处理的异常
    可以通过 catch 来进行捕获,通常遇到这种错误,应对其进行处理,使应用程序可以继续正常运行。
    Exception 又可以分为运行时异常(RuntimeException, 又叫非受检查异常)和非运行时异常(又叫受检查异常) 。
  • Error : Error 属于程序无法处理的错误 ,我们没办法通过 catch 来进行捕获 。
    例如,系统崩溃,内存不足,堆栈溢出等,编译器不会对这类错误进行检测,一旦这类错误发生,通常应用程序会被终止,仅靠应用程序本身无法恢复。

在这里插入图片描述

非受检查异常(运行时异常)和受检查异常(一般异常)区别是什么?

  • 非受检查异常:包括 RuntimeException 类及其子类,表示 JVM 在运行期间可能出现的异常。
    Java 编译器不会检查运行时异常。
    例如: NullPointException(空指针) 、 NumberFormatException(字符串转换为数字) 、 IndexOutOfBoundsException(数组越界) 、 ClassCastException(类转换异常) 、 ArrayStoreException(数据存储异常,操作数组时类型不一致) 等。

  • 受检查异常:是Exception 中除 RuntimeException 及其子类之外的异常。
    Java 编译器会检查受检查异常。
    常见的受检查异常有: IO 相关的异常、 ClassNotFoundException 、 SQLException 等。

非受检查异常和受检查异常之间的区别
是否强制要求调用者必须处理此异常,如果强制要求调用者必须进行处理,那么就使用受检查异常,否则就选择非受检查异常。


11. throw 和 throws 的区别

throws 是作用在方法声明上的上,可以抛出多个异常,用来标识该方法可能抛出的异常列表

public static void main(String[] args) throws IOException, ClassNotFoundException {
	...
}

throw 关键字用在方法内部,只能用于抛出一种异常,用来抛出方法或代码块中的异常,受查异常和非受查异常都可以被抛出。

if(s.equals("abc")) { 
	throw new NumberFormatException(); 
	} else { 
	System.out.println(s); 
	}

12. try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?变量怎么确定?

会执行,但是返回分2种情况

  • final中不return
    public static int getInt() { 
    	int a = 10; 
    	try {
    		System.out.println(a / 0); 
    		a = 20; 
    	} catch (ArithmeticException e) {
    		 a = 30;
    		 return a;
    		 /*
    		 * return a 在程序执行到这一步的时候,这里不是return a 而是 return 30; 这个返回路 径就形成了 
    		 * 但是呢,它发现后面还有finally,所以继续执行finally的内容,a=40 
    		 * 再次回到以前的路径,继续走return 30,形成返回路径之后,这里的a就不是a变量了,而是常量30 ; return 的是30  而不是a
    		 **/
    	} finally {
    		 a = 40; 
    	}return a; 
    }
    //执行结果:30
    
  • final中直接return
    public static int getInt() { 
    	int a = 10; 
    	try {
    		System.out.println(a / 0); 
    		a = 20; 
    	} catch (ArithmeticException e) {
    		 a = 30;
    		 return a;
    	} finally {
    		 a = 40; 
    		 //由于只能return 1个,所以直接return final里的a了
    		 return a; 
    	}
    }
    //执行结果:40
    

13. BIO、NIO、AIO的区别

  • BIO: 同步并阻塞,在服务器中实现的模式为一个连接一个线程。
    也就是说,客户端有连接请求的时候,服务器就需要启动一个线程进行处理
    BIO一般适用于连接数目小且固定的架构
  • NIO:同步并非阻塞,在服务器中实现的模式为一个请求一个线程。
    也就是说,客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到有连接IO请求时才会启动一个线程进行处理。
    NIO一般适用于连接数目多且连接比较短(轻操作)的架构
  • AIO:异步并非阻塞,在服务器中实现的模式为一个有效请求一个线程。
    也就是说,客户端的IO请求都是通过操作系统先完成之后,再通知服务器应用去启动线程进行处理。
    AIO一般适用于连接数目多且连接比较长(重操作)的架构,充分调用操作系统参与并发操作,编程比较复杂

14. Java IO都有哪些设计模式?

使用了适配器模式和装饰器模式

  • 适配器模式:
    Reader reader = new INputStreamReader(inputStream);
    
    在这里插入图片描述
  • 装饰器模式:
    new BufferedInputStream(new FileInputStream(inputStream));
    
    在这里插入图片描述
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值