Java之小笔记

1.数组容量如果不够用可以使用Arrays.copyOf()进行扩容:
Arrays.copyOf(A[]a,newLength);
其第一个形参指的是需要扩容的数组,后面是扩容后的大小,其内部实现是使用了System.arrayCopy(),在内部重新创建了一个长度newLength类型是A的数组
如int[]a=Arrrays.copyOf(a,a.length+1),输出的结果默认新加的长度的元素数据为0

2.在Java中%n只能用于printf的参数里,是一种格式化字符串,表示换行

3.java中检查型异常与非检查型异常的简单判断点:1.继承自Runtime Exception或Error的是非检查型异常,而继承自Exception的是检查型异常(Runtime Exception是Exception的子类)
2.对非检查型类异常可以不用捕获,而检查型异常则必须用try语句块进行处理或把异常交给上级方法处理,总之就是必须写代码处理它。

4.从大体来分异常为两块:
a.error—错误 : 是指程序无法处理的错误,表示应用程序运行时出现的重大错误。例如jvm运行时出现的OutOfMemoryError以及Socket编程时出现的端口占用等程序无法处理的错误。
b.Exception — 异常 :异常可分为运行时异常跟编译异常
1)运行时异常:即RuntimeException及其之类的异常。这类异常在代码编写的时候不会被编译器所检测出来,是可以不需要被捕获,但是程序员也可以根据需要进行捕获抛出。常见的RUNtimeException有:NullpointException(空指针异常),ClassCastException(类型转换异常),IndexOutOfBoundsException(数组越界异常)等。
2)编译异常:RuntimeException以外的异常。这类异常在编译时编译器会提示需要捕获,如果不进行捕获则编译错误。常见编译异常有:IOException(流传输异常),SQLException(数据库操作异常)等。

5.接下来看一下如何捕获异常:
1)首先java对于异常捕获使用的是try—catch或try — catch — finally 代码块,程序会捕获try代码块里面的代码,若捕获到异常则进行catch代码块处理。若有finally则在catch处理后执行finally里面的代码。然而存在这样两个问题:

a.看如下代码:

try{
//待捕获代码
}catch(Exception e){
System.out.println(“catch is begin”);
return 1 ;
}finally{
System.out.println(“finally is begin”);
}

在catch里面有一个return,那么finally会不会被执行呢?答案是肯定的,上面代码的执行结果为:
catch is begin
finally is begin

也就是说会先执行catch里面的代码后执行finally里面的代码最后才return1 ;

b.看如下代码:
try{
//待捕获代码
}catch(Exception e){
System.out.println(“catch is begin”);
return 1 ;
}finally{
System.out.println(“finally is begin”);
return 2 ;
}

在b代码中输出结果跟a是一样的,然而返回的是return 2 ; 原因很明显,就是执行了finally后已经return了,所以catch里面的return不会被执行到。也就是说finally永远都会在catch的return前被执行。(这个是面试经常问到的问题哦!)

6、对于异常的捕获不应该觉得方便而将几个异常合成一个Exception进行捕获,比如有IO的异常跟SQL的异常,这样完全不同的两个异常应该分开处理!而且在catch里处理异常的时候不要简单的e.printStackTrace(),而是应该进行详细的处理。比如进行console打印详情或者进行日志记录。
注意:异常和错误的区别:异常能被程序本身可以处理,错误是无法处理。

7.java不支持多继承,但支持多重继承
单继承:A类,B类 B extends A
多重继承:A类,B类,C类 B extends A;C extends B
不同类继承统一个类:A类,B类,C类 B extends A;C extends A
多继承(不支持):A类,B类,C类 C extends A,B

8.使用implement接口可以使java具有多继承的特性,如interface A,interface B,interface C,C implement A,B

9.final关键字:final关键字声明类可以把类定义为不能继承的,即最终类,或用于修饰方法,该方法不能被子类重写
注意:实例变量也可以被定义为final,被定义为final的变量不能被修改,被声明为final类的方法自动的声明为final,但是实例变量并不是final
final 修饰类中的属性或者变量:无论属性是基本类型还是引用类型,final 所起的作用都是变量里面存放的"值"不能变。
这个值,对于基本类型来说,变量里面放的就是实实在在的值,如 1,“abc” 等。
而引用类型变量里面放的是个地址,所以用 final 修饰引用类型变量指的是它里面的地址不能变,并不是说这个地址所指向的对象或数组的内容不可以变,这个一定要注意。
例如:类中有一个属性是 final Person p=new Person(“name”); 那么你不能对 p 进行重新赋值,但是可以改变 p 里面属性的值 p.setName(‘newName’);
final 修饰属性,声明变量时可以不赋值,而且一旦赋值就不能被修改了。对 final 属性可以在三个地方赋值:声明时、初始化块中、构造方法中,总之一定要赋值

10.a.如果父类中不含 默认构造函数(就是 类名() ),那么子类中的super()语句就会执行失败,系统就会报错。除非在构造函数代码体中的第一行显式调用父类有参构造函数。一般 默认构造函数 编译时会自动添加,但如果类中已经有一个构造函数时,就不会添加。
b.执行父类构造函数的语句只能放在函数内语句的首句,不然会报错。

11.向上转型与向下转型:a.父类引用指向子类对象,而子类引用不能指向父类对象。
b.把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转换
c.把指向子类对象的父类引用赋给子类引用叫向下转型
Father f1 = new Son(); // 这就叫 upcasting (向上转型)
// 现在 f1 引用指向一个Son对象
Son s1 = (Son)f1; // 这就叫 downcasting (向下转型)
// 现在f1 还是指向 Son对象

12.重写与重载的区别:方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。
(1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同**,返回值类型可相同可不同**,则称为方法的重载(Overloading)。
(2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
(3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

13.多态就是同一个接口,使用不同的实力而执行不同操作。多态性是对象多种表现形式的体现。
多态存在的三个必要条件:继承,重写,父类引用指向子类对象(即向上转型)
多态的实现方式:重写,接口,抽象类和抽象方法

Java 虚函数
虚函数的存在是为了多态。
C++ 中普通成员函数加上 virtual 关键字就成为虚函数。
Java 中其实没有虚函数的概念,它的普通函数就相当于 C++ 的虚函数,动态绑定是 Java 的默认行为。如果 Java 中不希望某个函数具有虚函数特性,可以加上 final 关键字变成非虚函数。

14.abstract 修饰符
抽象类:
抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。
一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误。

抽象类可以包含抽象方法和非抽象方法。
抽象方法
抽象方法是一种没有任何实现的方法,该方法的的具体实现由子类提供。
抽象方法不能被声明成 final 和 static。
任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。
如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。
抽象方法的声明以分号结尾,例如:public abstract sample();。

接口就是虚到极点的抽象类
C++ 虚函数 == Java 普通函数
C++ 纯虚函数 == Java 抽象函数
C++ 抽象类 == Java 抽象类
C++ 虚基类 == Java 接口

15 .抽象类和接口的区别
1、语法层面上的区别
1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。
2、设计层面上的区别
1)抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。举个简单的例子,飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类 Airplane,将鸟设计为一个类 Bird,但是不能将 飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。此时可以将 飞行 设计为一个接口Fly,包含方法fly( ),然后Airplane和Bird分别根据自己的需要实现Fly这个接口。然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承Airplane即可,对于鸟也是类似的,不同种类的鸟直接继承Bird类即可。从这里可以看出,**继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。**如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。

2)设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。什么是模板式设计?最简单例子,大家都用过 ppt 里面的模板,如果用模板 A 设计了 ppt B 和 ppt C,ppt B 和 ppt C 公共的部分就是模板 A 了,如果它们的公共部分需要改动,则只需要改动模板 A 就可以了,不需要重新对 ppt B 和 ppt C 进行改动。而辐射式设计,比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新。也就是说对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。

下面看一个网上流传最广泛的例子:门和警报的例子:门都有 open() 和 close() 两个动作,此时我们可以定义通过抽象类和接口来定义这个抽象概念:

abstract class Door {
public abstract void open();
public abstract void close();
}
或者:

interface Door {
public abstract void open();
public abstract void close();
}
但是现在如果我们需要门具有报警 的功能,那么该如何实现?下面提供两种思路:

1)将这三个功能都放在抽象类里面,但是这样一来所有继承于这个抽象类的子类都具备了报警功能,但是有的门并不一定具备报警功能;

2)将这三个功能都放在接口里面,需要用到报警功能的类就需要实现这个接口中的 open( ) 和 close( ),也许这个类根本就不具备 open( ) 和 close( ) 这两个功能,比如火灾报警器。

从这里可以看出, Door 的 open() 、close() 和 alarm() 根本就属于两个不同范畴内的行为,open() 和 close() 属于门本身固有的行为特性,而 alarm() 属于延伸的附加行为。因此最好的解决办法是单独将报警设计为一个接口,包含 alarm() 行为,Door 设计为单独的一个抽象类,包含 open 和 close 两种行为。再设计一个报警门继承 Door 类和实现 Alarm 接口。

interface Alram {
void alarm();
}

abstract class Door {
void open();
void close();
}

class AlarmDoor extends Door implements Alarm {
void oepn() {
//…
}
void close() {
//…
}
void alarm() {
//…
}
}

16.重写接口中声明的方法时,需要注意以下规则:
a.类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
b.类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
c.如果实现接口的类是抽象类,那么就没必要实现该接口的方法。
在实现接口的时候,也要注意一些规则:
a.一个类可以同时实现多个接口。
b.一个类只能继承一个类,但是能实现多个接口。
c.一个接口能继承一个或多个接口,这和类之间的继承比较相似。interface C extends A,B{}

17.标记接口
最常用的继承接口是没有包含任何方法的接口
没有任何方法的接口被称为标记接口。标记接口主要用于以下两种目的:
建立一个公共的父接口
正如EventListener接口,这是由几十个其他接口扩展的Java API,你可以使用一个标记接口来建立一组接口的父接口。例如:当一个接口继承了EventListener接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。
向一个类添加数据类型:
这种情况是标记接口最初的目的,实现标记接口的类不需要定义任何接口方法(因为标记接口根本就没有方法),但是该类通过多态性变成一个接口类型。

18.在 JDK1.8,允许我们给接口添加两种非抽象的方法实现:
1、默认方法,添加 default 修饰即可;
2、静态方法,使用 static 修饰
;示例如下:
interface Test{
//这个是默认方法
default String get(String aa){
System.out.println(“我是jdk1.8默认实现方法…”);
return “”;
}
//这个是静态方法
static void staticmethod(){
System.out.println(“我是静态方法”);
}
}

调用的话,静态方法只能通过接口名调用,不可以通过实现类的类名或者实现类的对象调用,default 方法只能通过接口实现类的对象来调用。

19.通常,一个公司使用它互联网域名的颠倒形式来作为它的包名.例如:互联网域名是 runoob.com,所有的包名都以 com.runoob 开头。包名中的每一个部分对应一个子目录。
例如:有一个 com.runoob.test 的包,这个包包含一个叫做 Runoob.java 的源文件,那么相应的,应该有如下面的一连串子目录:
…\com\runoob\test\Runoob.java

20.java迭代器Iterator的详解:(https://blog.csdn.net/qq_33642117/article/details/52039691)

21.泛型的详解:(https://blog.csdn.net/s10461/article/details/53941091)

22.Java中String栈内存与堆内存:(https://www.cnblogs.com/kenshinobiy/p/4651990.html)

23.空格,数字和符号(!"#$%&’()*+,-./:;<=>?@[]^_{|}~)组成的正则表达式:
String regex="[\s\d\p{Punct}]+";

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值