抽象类与接口,重载与重写,superAndthis,System.out.println与System.err.println,初始代码块,Java8接口新定义

这也是一道面试题,但是我发现牵扯的知识点很多很杂,于是我自己整理了一下,没有完成后期还是会在完善的.

3抽象方法

选项中哪一行代码可以替换 //add code here 而不产生编译错误

public abstract class MyClass {
public int constInt = 5;
//add code here
public void method() {
}
}
A public abstract void method(int a);
B consInt=constInt+5;
C public int method();
D public abstract void anotherMethod(){}
正确答案选择 A
对于这个问题我们先看题目
第一眼看过去能够看得到这个涉嫌到抽象类的问题
这也是面试笔试经常会用得到的问题

1接口和抽象类的区别

在搞清楚区别之前我们需要先确定一下量这到底是什么

接口:interface

Java中的接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征,没有方法的实现,
因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
和类定义不同,定义接口不再使用class关键字,而是使用interface关键字,也就是说接口并不是一个实际意义上的类。
接口方法只有方法头没有方法体(这是在Java8之前以后,Java8发生了大的改变)
一个接口可以有多个直接父接口,但接口只能继承接口,不能继承类,接口定义的是一种规范,
因此接口里不能包含构造器和初始化块定义。

接口里可以包含Field(字段,成员变量)、方法、内部类定义。
因为接口没有构造器与初始化块,因此系统不能为field进行默认的初始化操作,只能由程序编写人员为field指定默认的值,所以field只能是常量。
又因为field只能是常量,所以系统自动为这些field增加了static和final两个修饰符。
也就是说在接口中定义的Field不管是否使用了public static final修饰符,接口里的Field总是默认的使用这三个修饰符来进行修饰。
接口里定义的方法都是抽象方法,因此系统会自动为方法增加public abstract修饰符。
不管定义接口方法时是否使用了public abstract修饰符,系统都会默认的使用public abstract修饰符来进行修饰。
接口的继承与类的继承不一样,接口完全支持多继承,即一个接口可以有多个直接父接口。和继承相似,子接口扩展父接口,将会获得父接口里定义的所有抽象方法、field、内部类和枚举定义。
一个接口继承多个父接口时,多个父接口排在extends关键字之后,多个父接口之间使用英文逗号(,)进行分隔。public interface InterfaceC extends InterfaceA, InterfaceB {

抽象类,抽象方法:abstract

1、 抽象类与抽象方法必须使用abstract关键字进行修饰,抽象方法不能有方法体(没有方法体不是空方法)。
2、 抽象类不能被实例化。即使抽象类不包含抽象方法,也不能被实例化。
3、 抽象类可以包含变量、方法、构造器、初始化块、内部类5种成分。类 + 抽象方法
4、 包含抽象方法的类,只能被定义成抽象类。
abstract 与 final和static 不可同时出现。

接口和抽象类的区别
相同点:

1、接口和抽象类都不能进行实例化,它们都位于继承树的顶端,用于被其他类实现和继承。
2、接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。

不同点:

接口作为系统与外界交互的窗口,接口体现的是一种规范。对于接口的实现者而言,接口规定了实现者必须向外提供哪些服务。对于接口的调用者而言,接口规定了调用者可以调用哪些服务。当在一个程序中使用接口时,接口是多个模块间的耦合标准,当在多个应用程序之间使用接口时,接口是多个程序之间的通信标准。
接口类似于系统的总纲,一旦接口发生变化,对于整个系统是辐射式的,所有实现这个接口的普通类都要进行改写。抽象类则不一样,抽象类作为系统中多个子类的共同父类,它所体现的是一种模版式设计。抽象类作为多个子类的抽象父类,可以被当成系统实现过程中的中间产品。这个中间产品已经实现了系统的部分功能,但这个类不能称为最终产品,必须有更进一步的完善,这种完善可能有几种不同的方式来实现。
接口与抽象类在用法上也存在如下差异:
 接口里只能包含抽象方法,不包含已经提供实现的方法(Java8中已经可以了),抽象类则完全可以包含普通方法。
 接口里不能定义静态方法(Java8中已经可以了),抽象类里可以定义静态方法。
 接口里只能定义静态常量Field,不能定义普通的Field,抽象类里则都可以
 接口里不包含构造器,抽象类里可以包含构造器,抽象类里的构造器并不是用来创建对象,而是让其子类调用这些构造器完成属于抽象类的初始化操作。
 接口里不能包含初始化块,但抽象类则完全可以包含初始化块。
 一个类最多只有一个父类,包括抽象类,但是一个类可以实现多个接口。

2我们要清楚重载和重写的区别

我们先要该清楚重载(overload)是什么

我在网上查阅了一下没有具体描述重载的种类
就只是找了这两张类型,一种是构造器重载,一种是正常的方法重载
同一个类里具有多个构造器,多个构造器的形参列表不同,即被称为构造器重载。
Java允许同一个类里定义多个同名方法,只要形式参数列表不同就行。如果同一个类中包含了两个或两个以上方法的方法名相同,但形参不同,则被称为方法重载。至于方法的其他部分,如方法返回值类型、修饰符等与方法重载没有任何关系。

重写(override)的定义是什么呢

子类扩展了父类,子类是一个特殊的父类。大部分情况下子类总是以父类为基础,额外增加新的Field和方法.但是有一种特殊的情况例外:子类需要重写父类的方法。
程序执行时,这种子类包含与父类同名方法的现象称为重写,也称为方法覆盖(Override)。
方法的重写要遵循如下规则:
1、 方法名相同、形参列表相同
2、 子类方法返回值类型应比父类方法返回值类型相等或者更小。返回值类型比父类的要小,这个返回值一定是有父子关系才行的,基本类型之间没有父子关系。
3、 子类方法声明抛出的异常类应该比父类方法更小或相等。
4、 子类权限比父类权限大或者相等。
当子类覆盖了父类方法后,子类对象将无法访问父类中被覆盖的方法,但可以在子类方法中调用父类中被覆盖的方法,需要使用super关键字。如果父类方法具有private访问权限,则该方法对其子类是隐藏的,也就无法重写该方法。如果子类中定义了一个与父类private方法相同的方法名、相同形参列表、相同返回值类型的方法,依然不是重写,只是在子类中定义了一个新的方法而已。
(那么super是什么呢,下文中有写)

3super and this

super

1、super.变量/对象名;
使用这种方法可以直接访问父类中的变量或对象,进行修改赋值等操作
2、super.方法名();
直接访问并调用父类中的方法
3、super();
调用父类的初始化方法`,其实就是调用父类中的public xxx()方法,通常第三种指代的是super()的省略写法,系统会默认.

this

1、构造器中引用,this指的是该构造器正在初始化的对象。
2、在方法中引用,this指的是调用该方法的对象。
this关键字最大的作用就是让类中一个方法,访问该类里的另一个方法或字段。

4小问题

我在时间super的作用的时候自己敲了一段代码然后出现了神奇的问题,就是System.out.println和System.out.println的问题,
代码在下面会站出来欢迎我们一起的讨论

package com.langsin.com;

class aaa {
	int a=10;
	void add(){
		System.out.println(a);
		}
	
}
class bbb extends aaa{
	int a=11;
	void add(){
		System.out.println(a);
		System.out.println(super.a);
		super.add();
		System.out.println(this.a);
		System.err.println("11");
		}
}

class ccc extends bbb{
	void add(){
		System.out.println(a);
		}
	int a=12;
}
public class SuperAndThis {
public static void main(String[] args) {
	aaa aa=new aaa();
//	aa.add();	
	bbb bb=new bbb();
	bb.add();
	ccc cc=new ccc();
//	cc.add();
}

}

在这里插入图片描述
在这里插入图片描述
这段代码,执行会有两种的结果,我开始还以为是有println的方法的问题
我之前知道了println的源码里面是有synchronized代码块的

    public void println(int x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }

这就是System.out.println的源码,在往下就是跑到了输出流和输入流
这里是用了一个所以synchronized的代码块,保证了线程的安全,只能允许一个线程执行,然后我就单独跑了一个类去遍历

 for (int i = 0; i < 100; i++) {
 	System.out.println(i);
//		System.err.println(i);
 }
 }

在这里插入图片描述我先单独的遍历了for循环然后使用System.out.println发现并没有出现格式混乱的事

	for (int i = 0; i < 100; i++) {
		System.out.println(i);
		System.err.println(i);
	}
    }

然后是加上System.err.println的形式
在这里插入图片描述
就出现了乱码
原因就是因为System.out.println和System.err.println是两个不同的流
out这个流是存在缓存的,而err则没有他是马上就打印了
然后就是out这个流打印需要系统(os)和Java虚拟机(JVM)一起同意才能输出,但是如果一者不同输出就会出现问题,要么就是不打印,或者打印的位置不在你想要的位置
但是err呢,就是一旦输出直接打印不存在缓存,并且直接输出到什么地步呢,就是有的时候输出会在换行的前面,会先输出在换行,所以会出现看起来像是多线程的样子.

5Java8定义接口新概念

default关键字定义方法:在接口中使用default关键字定义方法,需要添加方法体,default见名思意就是说,为这个方法提供一个默认写好的方法体实现。当然,在子接口中也可以继续去覆写它。
用Static关键字定义方法:我们知道,在java中,使用static关键字修饰的方法叫做静态方法,它不依赖于某个对象就可以访问。在接口中定义static方法也是如此,可以通过接口名直接调用。

(刚才自己去定义了一个借口得到了一些定义接口的新知识
接口中定义方法时:定义 返回值类型 函数名();只能定义方法头
但是如果添加了default,和static之后就可以添加方法体,而且是强制的添加

)

6初始化块:初始化块是什么呢?

在Java中,有两种初始化块:静态初始化块和非静态初始化块。它们都是定义在类中,用大括号{}括起来,
静态代码块在大括号外还要加上static关键字。
非静态初始化块(构造代码块):
作用:给对象进行初始化。对象一建立就运行,且优先于构造函数的运行。
与构造函数的区别:非静态初始化块给所有对象进行统一初始化,构造函数只给对应对象初始化。
应用:将所有构造函数共性的东西定义在构造代码块中。
静态初始化块:
作用:给类进行初始化。随着类的加载而执行,且只执行一次
与构造代码块的区别:
1)构造代码块用于初始化对象,每创建一个对象就会被执行一次;静态代码块用于初始化类,随着类的加载而执行,不管创建几个对象,都只执行一次。
2)静态代码块优先于构造代码块的执行
3)都定义在类中,一个带static关键字,一个不带static
构造函数、非静态初始化块、静态代码块都是用于初始化,三者的执行顺序依次是:静态代码块>构造代码块>构造函数。
其实初始化块就是构造器的补充,初始化块是不能接收任何参数的,定义的一些所有对象共有的属性、方法等内容时就可以用初始化块初始化了。
静态初始化块的作用就是当JVM在装载类时,你想让它做一些事情,那么,就可以用静态初始化块。这几者的执行顺序是:
(JVM在装载类时)先装载类的静态成员,再执行静态初始化块(同样,当一个类有继承自某类时,则会先装载该父类,那么,父类的装载或执行顺序,也都如句子所述)。
(在创建类的实例时)先执行实例初始化块,再执行构造方法;但对于一棵继承树中,会先调用父类的构造方法,那么其执行顺序也如句子所述。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

又是重名了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值