JAVA基础--个人笔记
博客说明
Java基础系列博客用于记录一些java的小的知识点,包括以前书上学到的、自己笔记上记录的、网上看到的…知识点较为繁杂,来源也很多样。所以如果有侵权的情况请与我联系,我会及时删除或提供出处。由于是个人的小笔记,所以会不时更新,有不对或者不太准确的描述,请各位大牛指正!
JAVA四大基础特性
JAVA基础之四大特性包括 抽象、封装、继承、多态。
一. 继承 :
1.描述:父类为子类提供一些属性和行为,但不提供具体实现,由子类根据业务的需求实现具体的行为。
2.理解:比方说有几个方法会被很多类用到,但是在各个类中具体的实现可能又会有细节上的差别。那我就可以用一个抽象类来把这些方法抽象出来,但不关心其具体的实现。
3.扩展:抽象类与接口挺像的,主要都是用来抽象出方法,由实现类进行具体的实现。但是两者又有所不同:
(1)抽象类中可以提供某些方法的部分实现,这样就可以让所有的实现类获得这个方法的实现,而接口的方法不能提供实现。
(2)抽象类可以声明和使用字段,接口只能创建静态final的常量。
(3)抽象类中的方法可以是public或者protected,而接口中只能为public。
(4)抽象类可以有构造方法,而接口却不能。
二.封装:
1.描述:隐蔽对象的属性及实现细节,仅对外公开访问接口,控制外部访问对外接口的访问权限,使对象内部数据及操作结合为一个整体–通常是类。
2.理解就像现在的很多api一样,只会提供给你接口,不会让你知道内部的具体实现,既增强了安全性,也简化了使用的成本。
3.扩展根据OO原则之一的SRP–单一职责原则,每一个类/模块只负责一项任务,所以会大量地使用封装,然后将多个封装好的模块结合起来实现某些功能。
三.继承:
1.描述:子类继承父类,可以继承父类的属性和方法,并可以扩展。降低了代码的复用。
2.理解:举个例子。在我们做项目中,会有大量的实体类对象,虽然实体类对象的属性大不相同,但是为了对实体类进行标识和管理,我们通常会给实体类加上createTime(创建时间)、version(版本)等属性,因此我们可以创建一个所有实体类的父类(BaseEntity),这样就不需要在所有的实体类中加上这些基础属性了。方法也是一样,子类可以继承父类的方法,也可以重写父类的方法,更可以扩展属性和方法。
3.扩展子类重写/实现父类的方法时,除了实现内容可以不同外,返回类型、方法名、参数都必须相同,权限修饰符只能由小往大变化,如由protected变为public。与重载不同,重载只需要方法名相同,然后与参数有关、与返回类型权限修饰符等无关。
四.多态
1.描述:在引用上是父类的引用但是实际上的实现是其子类的实现方式
2.理解:从代码层面来说,多态就是对于继承或者封装的体现。比如说父类是Animal,有个cry方法,子类是Cat和Dog,都重写了cry方法。在使用的时候,引用的是Animal,但是实际 上使用的是某个子类的实现方法。
Animal animal = new Dog();
animal.cry();
3.扩展:多态其实又分为编译时多态和运行时多态。编译多态是指在编译时能够确定执行多态方法中的哪一个,如方法重载。反之则为运行时多态。如上文提到的Animal的案例。
同时,所谓静态,就是在运行时,虚拟机已经认定此方法属于哪个类。重写只能适用于实例方法,不能用于静态方法,也就是说父类的静态方法无法被重写。比如上文提到的Animal类里面有一个属性name,还有一个静态方法getName(),子类也有一个同名的属性和同名的静态方法,然而在调用name和getName时调用的其实是父类Animal的属性和方法。对于静态方法只能隐藏、重载、继承。父类中的属性只能被隐藏。
Animal animal = new Dog();
animal.cry();
animal.name;
animal.getName();
static和final关键字
static关键字:
1.描述:static意思是“静态的”,可用于修饰属性和方法。
2.理解:
(1)static作用于某个字段时,该字段对每个类来说只有一份存储空间,而非static字段是每个实际对象都有一份存储空间。
(2)static作用于方法时,不需要创建任何对象可直接调用该static方法,
(3)static不能应用于局部变量。
(4)Java中禁止使用全局方法,所以引入static方法通过类本身来调用。如各种Util类中的static方法。
3.扩展:类的加载和初始化过程中,带有static的数据会最先被加载和调用,其次是构造器的加载,最后才是普通成员变量和方法的加载。
final关键字:
1.描述:final意味着不可改变的,一般应用于数据、方法和类。
2.理解:
(1)修饰数据:一旦定义了 final 变量并在首次为其显示初始化后,final修饰的变量值不可被改变。a、修饰的变量,无论是类属性、对象属性、形参还是局部变量,这些变量都是需要进行显示初始化(即为其显示指定初始值)。 b、对于一般的类属性和对象属性,由类和对象的初始化过程中可以看出,首先都进行了默认初始化。然后对有显示赋值的变量才再进行显示初始化。但对final修饰的类属性和对象属性而言,如果不显示初始化,其默认将是进行默认初始化后的值,这与final本身出发点矛盾,因此,Java语法规定:final修饰的类属性和变量属性必须要进行显示初始化赋值。 c、另外,无论对于基本数据类型还是引用数据类型,final修饰的变量都是首次显示初始化后值都不能修改。对于基本数据类型,很好理解。对于引用数据类型,引用变量指向的是实际的对象,但其存储的是所指向对象的地址,因此,其值不能修改并不意味着其所指向的对象不能修改。
(2)修饰方法:final修饰的方法表示此方法已经是“最后的、最终的”含义,亦即此方法不能被重写(可以重载多个final修饰的方法)。但是需要注意的一点是:因为重写的前提是子类可以从父类中继承此方法,如果父类中final修饰的方法同时访问控制权限为private,将会导致子类中不能直接继承到此方法,因此,此时可以在子类中定义相同的方法名和参数,此时不再产生重写与final的矛盾,而是在子类中重新定义了新的方法。
(3)修饰类:用final修饰的类无法被继承。
3.扩展:static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。
Lambda表达式
基础语法
左侧:表达式的参数列表
右侧:表达式中所需执行的功能,即Lambda体。
语法格式
语法格式一:无参数,无返回值
()->System.out.println("Hello Lambda");
语法格式二:有一个参数,并且无返回值
(x)->System.out.println(x);
语法格式三:若是只有一个参数,小括号可以省略不写,但是一般习惯写上。
语法格式四:有两个以上的参数,并且Lambda体中有多条语句
Comparator<Integer> com = (x, y) -> {
System.out.pringln("函数式接口");
return Integer.compare(x,y);
};
语法格式五:若lambda体中只有一条语句,return和大括号都可以省略不写
Comparator<Tnteger> com = (x,y) -> Integer.compare(x,y);
语法格式六:Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编辑器可以通过上下文推断出数据类型,即“类型推断”
(Integer x, Integer y) -> Integer.compare(x,y);
小结:左右遇一括号省,左侧推断类型省
函数式接口
描述:Lambda 表达式需要“函数式接口”的支持函数式接口:接口中只有一个抽象方法的接口,成为函数式接口。可以使用注解@FunctionalInterface 修饰可以检查是否是函数式接口。
Java8 内置的四大核心函数式接口
1、Comsumer : 消费型接口 void accept(T t)
2、Supplier : 供给型接口 T get()
3、Function<T, R> : 函数型接口 R apply
4、Predicate : 断言型接口 boolean test(T t)
方法引用
描述:若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”(可以理解为方法引用是Lambda表达式的另外一种表现形式)
三种语法格式:
1、对象::实例方法名
2、类::静态方法名
3、类::实例方法名
注意事项:
1、Lambda体中调用方法的参数列表与返回值类型,要与函数式接口中的抽象方法的函数列表和返回值类型保持一致!
2、若Lambda参数列表中的第一参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::method (类::实例方法名)