1.抽象类
类的继承的主要作用在于扩充已有类的功能,但是对于之前的继承操作而言,子类可以由自己选择任意的来决定选择是否要覆写某一个方法。这个时候父类无法对子类做出强制性约定(强制性你必须覆写某些方法),这个时候往往不会采用类的继承(在实际开发中,很少会出现继承一个已经完善的类,可以直接使用的类,而是必须要继承一个抽象类),在以后进行父类设计的时候,优先考虑的一定是抽象类。
抽象类的基本定义:
抽象类的主要作用是对子类中已经覆写的方法进行约定,在抽象类里面可以定义一些抽象方法,以实现这样的约定
- 抽象类与普通类的区别,普通类类名加上abstract并且类里面存在不含抽象方法体的抽象方法
- 抽象方法自己 无法直接实例化,不能通过new创建对象
- 定义抽象方法的时候,不能用private,static,final修饰抽象方法,但可以在抽象类内用static定义普通方法
抽象方法局就类似于一个接口,专门等着覆写,如果用private、final、修饰将不允许覆写,而static修饰可以理解为属于类的固有属性,是类自己的东西,不是给子类来继承的。
抽象类定义完成后(抽象类不是一个完整的类),如果要去使用抽象类,有以下原则:
- 抽象类必须提供有子类,子类使用extends继承一个抽象类
- 抽象类的子类(不是抽象类)一定要覆写抽象类中的全部抽象方法
抽象类为什么不能直接实例化?
- 抽象类只在分配了在栈中的引用,没有分配堆中的内存。程序都有一个代码段,再内存中需要占据一定的内存,而抽象类没有具体的实现方法,无法具体的给它分配内存空间,所以为了安全,不JAVA不允许抽象类,接口直接实例化
- 抽象类,就像是向别人声明:我能赚大钱
实例化就是具体的行动
因为抽象类只是个声明,而没有计划,也不知道怎么赚钱
所以我们是不会投资给钱(内存)他的,就算投资他他也不能做任何事
为了保存大家的利益,没有具休的赚钱计划不能让他执行
抽象类如何实例化?
- 抽象类的实例化可以用对象的多态性通过子类向上转型的方式完成
- 抽象类的实例化还可以通过内部类实现抽象方法的方式实现实例化(若抽象类不含抽象方法则无法实例化)
abstract class Demo{
private String types;
public abstract void getInfo();
public void setTypes(String types){
this.types=types;
}
public String getTypes(){
return this.types;
}
}
class MessageDemo extends Demo{
@Override
public void getInfo() {
System.out.println("继承实现了抽象方法");
}
}
public class javademo {
public static void main(String[] args) {
Demo demo=new MessageDemo();
demo.getInfo();
Demo D=new Demo() {
@Override
public void getInfo() {
System.out.println("内部类的方式实现了抽象方法");
}
};
D.getInfo();
}
}
//----输出:
//继承实现了抽象方法
//内部类的方式实现了抽象方法
抽象类的设计模式:模板结构的设计,要想实现某些功能就按照父类要求把方法写
- 对子类方法的统一管理,在父类定义的方法要全部实现,而子类自己定义的父类不认,就像是填写表格,一个信息一个位置,不能填表内不存在的标题
- 再者,抽象类中可以定义一些普通方法,这些普通方法可以调用抽象方法
abstract class Action{
public static final int EAT=1;
public static final int SLEEP=5;
public static final int WORK=10;
public void setCommend(int commend){
switch (commend){
case EAT:
eat(); //普通方法调用抽象类的方法
break;
case SLEEP:
sleep();
break;
case WORK:
work();
break;
case EAT+SLEEP+WORK:
eat();sleep();work();
break;
}
}
public abstract void eat();
public abstract void sleep();
public abstract void work();
}
class Robot extends Action{
@Override
public void eat() {
System.out.println("机器人不需要吃饭");
}
@Override
public void sleep() {
System.out.println("机器人不需要睡觉");
}
@Override
public void work() {
System.out.println("机器人一直工作");
}
}
class Human extends Action{
@Override
public void eat() {
System.out.println("人类需要吃饭");
}
@Override
public void sleep() {
System.out.println("人类需要睡觉");
}
@Override
public void work() {
System.out.println("人类需要工作");
}
}
public class javademo {
public static void main(String[] args){
Action robot=new Robot(); //向上转型才能实例化抽象类
System.out.println("-------机器人的行为------");
robot.setCommend(Action.SLEEP);
robot.setCommend(Action.WORK);
System.out.println("-------人类的行为------");
Action human=new Human();
human.setCommend(Action.WORK);
human.setCommend(Action.SLEEP);
human.setCommend(Action.EAT);
}
}
//---输出:
//-------机器人的行为------
//机器人不需要睡觉
//机器人一直工作
//-------人类的行为------
//人类需要工作
//人类需要睡觉
//人类需要吃饭
2.接口
接口定义的加强:
当很多个类都继承了同一个接口,那么如果要给一个接口添加方法,那么以下所有的类都需要实现这个接口,这个时候可以在接口类定义 特殊的方法使得不需要再在每个类都实现一次,default 的使用
interface Action{
public void show();
public default void show2(){
System.out.println("这是不需要必须实现类重写的方法");
}
}
class Robot implements Action {
@Override
public void show() {
System.out.println("这是必须要实现类重写的方法");
}
}
public class javademo {
public static void main(String[] args){
Action action=new Robot();
action.show();
action.show2();
}
}
//-----输出:
//这是必须要实现类重写的方法
//这是不需要必须实现类重写的方法
接口延伸到工厂模式:
经常我们需要实现接口的方法都是通过 new 的方式,这样就要就你确定的知道具体哪个类,然而如果越来越多的话就很难区分,而且这样带来的耦合性很大( 就像近代时期的地下党组织,每个人都单线联系,这就导致了如果中间哪个领导不幸被俘,那么他直线领导下的特工就直接失去联系)
这时候就引入一个工厂模式,指定一个端口,里面有庞大的信息,调用这个端口就可以调用里面的所有方法,而不需要确定性的知道要 new 哪个类。
interface Action{
void run();
}
class Robot implements Action {
@Override
public void run() {
System.out.println("我是机器人我可以跑");
}
}
class Human implements Action {
@Override
public void run() {
System.out.println("我是人类我可以跑");
}
}
class Factory {
public static Action getInstance(String className) {
if ("human".equals(className)) {
return new Human();
} else if ("robot".equals(className)) {
return new Robot();
} else {
return null;
}
}
}
public class Javademo {
public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
String className=scanner.nextLine();
Action action=Factory.getInstance(className);
action.run();
}
}
//-----输入:human
//-----输出:我是人类我可以跑
2.Arrays工具类用法归总
Arrays.sort()
Arrays.sort():升序排序
Arrays.sort (int[] a , int start , int end):从start索引到end索引范围内进行排序
官方文档:Sorts the specified range of the array into ascending order
int [] ints = {18,75,62,12,36,26};
Arrays.sort(ints);
for (Integer integer:ints){
System.out.print(integer+",");
}
//输出: 12,18,26,36,62,75,
int [] ints = {18,75,62,12,36,26};
Arrays.sort(ints,1,6);
for (Integer integer:ints){
System.out.print(integer+",");
}
//输出: 18,12,26,36,62,75,
Arrays.binarySearch ()
Arrays.binarySearch (int[] a,key):查找数组里面是否有某个值,返回索引
Arrays.binarySearch(int[] a, int fromIndex, int toIndex, int key):从 start 索引到 end 索引范围内进行查找
官方文档:index of the search key, if it is contained in the array within the specified range
int index = Arrays.binarySearch(ints,75);
System.out.println(index);
//输出: 5
Arrays.equals()
Arrays.equals( int[] a, int[] a2):比较两个数组是否相等(必须要求两个数组的位置和元素都一样才返回 true)
官方文档:In other words, two arrays are equal if they contain the same elements in the same order. Also, two array references are considered equal if both are null
int [] ints = {18,75,62,12,36,26};
int[] ints2 = {18,75,62,12,36,26};
int[] ints3 = {18,75,62,12,36,26};
System.out.println(Arrays.equals(ints,ints2));
System.out.println(Arrays.equals(ints2,ints3));
//输出: false
// true
Arrays.deepEquals()
Arrays.deepEquals( int[] a, int[] a2):与equals类似,只是用于深度相等(即用于判定两个指定数组彼此是否深层相等,此方法适用于任意深度的嵌套数组)
int [] ints = {18,75,62,12,36,26};
int[] ints2 = {18,75,62,12,36,26};
int[] ints3 = {18,75,62,12,36,26};
System.out.println(Arrays.equals(ints,ints2));
System.out.println(Arrays.equals(ints2,ints3));
//输出: false
// true
String[][] name1 = {{ "G","a","o" },{ "H","u","a","n"},{ "j","i","e"}};
String[][] name2 = {{ "G","a","o" },{ "H","u","a","n"},{ "j","i","e"}};
System.out.println(Arrays.equals(name1, name2)); // false
System.out.println(Arrays.deepEquals(name1, name2));// true
String[] name3 = {"G","a","o","H","u","a","n","j","i","e"};
String[] name4 = {"G","a","o","H","u","a","n","j","i","e"};
System.out.println(Arrays.equals(name3, name4)); // true
System.out.println(Arrays.deepEquals(name3, name4)); // true
Arrays.fill()
Arrays.fill( int[] a, int val):给每个元素分配val
Arrays.fill( int[] a, int fromIndex, int toIndex, int val):在一定范围内给每个元素分配val
官方文档:Assigns the specified int value to each element of the specified array of ints.
Assigns the specified int value to each element of the specified range of the specified array of ints
for (Integer integer:ints2){
System.out.print(integer+",");
}
System.out.println("");
Arrays.fill(ints2,99);
for (Integer integer:ints2){
System.out.print(integer+",");
}
//输出:
18,75,62,12,36,26,
99,99,99,99,99,99,
for (Integer integer:ints2){
System.out.print(integer+",");
}
System.out.println("");
Arrays.fill(ints2,1,3,99);
for (Integer integer:ints2){
System.out.print(integer+",");
}
//输出:
18,75,62,12,36,26,
18,99,99,12,36,26,
Arrays.copyOf()
Arrays.copyOf( T[] original, int newLength): 传入参数包括需要被复制的数组对象以及长度,长度比原数组长的话用零填充
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
// Arrays.copyOf传入参数包括需要被复制的数组对象以及长度,长度比原数组长的话用零填充
//底层调用的是System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
src:源对象
srcPos:源数组中的起始位置
dest:目标数组对象
destPos:被复制的数组接到目标数组的插入起始位置
length:要拷贝的数组元素的数量
输出: [9, 8, 7, 6, 10, 20, 1, 2, 3, 4, 5]
Arrays.copyOfRange()
Arrays.copyOfRange( (U[] original, int from, int to,): 复制数组从from 到 to
官方文档:Copies the specified range of the specified array into a new array. The initial index of the range (from) must lie between zero and original
int [] newArrays = Arrays.copyOfRange(copyArrays3,1,6);
for (Integer integer:newArrays){
System.out.print(integer+",");
}
Arrays.toString()
Arrays.toString(): 返回指定数组内容的字符串表示形式
官方文档:Returns a string representation of the contents of the specified array.
int [] copyArrays4 ={1,2,3,4,5};
System.out.println(Arrays.toString(copyArrays4));
// 输出: [1, 2, 3, 4, 5]
Arrays.asList()
Arrays.asList(): 将字符串转化为数组
官方文档:Returns a fixed-size list backed by the specified array. (Changes to the returned list “write through” to the array.)
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
for (String str : stooges){
System.out.println(str);
}
// Larry
// Moe
// Curly