Java第五课回顾
常用API
Scanner
int nextInt()
String next()
String
通过xx来构造对象: String char[] byte[]
int length()
int indexOf(char/String[, index])
boolean equals(String)
String substring(int start[, int end])
System
static long currentTimeMills()
static void arraycopy(src, int srcPos, dest, destPos, length)
Arrays
static String toString(array)
static void sort(array)
int[] copyOf(int[], int newLength)
面向对象:
类: 成员变量\成员方法\静态方法\静态成员变量\构造方法\静态代码块\代码块
成员变量\成员方法 在使用之前必须要创建对象
静态方法\静态成员变量 可以直接通过类来调用
**
Matn类,ArrayList类
**
public class Demo06 {
public static void main(String[] args) {
double ceil = Math.ceil(4.45);// double ceil(double) : 向上取整
System.out.println(ceil);//5.0
double floor = Math.floor(4.45);//double floor(double): 向下取整
System.out.println(floor);4.0
double round = Math.round(4.55);// double round(double): 四舍五入
System.out.println(round);//4.0
double sqrt = Math.sqrt(4);//double sqrt(double): 开方
System.out.println(sqrt);//2.0
double random = random();// static double random(): 0.0~1.0
System.out.println(random);
double x = Math.random();// 0.0~1.0
System.out.println(x);
double pow = Math.pow(3,2);//static double pow(double a, double b)3的2次方
System.out.println(pow);//9.0
int abs = Math.abs(-3);//static int abs(int) : 求绝对值
System.out.println(abs);//3
}
static double random(){
double random = Math.random();
return random;
}
}
ArrayList - 类
用来存储数据, 可变长数组 -> 集合
所属软件包: java.util
数组长度不可变, 数组如果要扩容, 需要用到数组的复制
为了解决数组长度不可变的问题, 可以实现数组长度动态变化
int[] Student[] int[][] Room[][]
ArrayList 仅支持引用类型
1.构造方法
空参构造器: 没有内容的空的集合
ArrayList arrList = new ArrayList()
: 泛型, 可以所有的引用类型, 规定集合中元素类型的
基本数据类型都有对应的引用类型
int -> Integer
char -> Character
byte -> Byte
boolean -> Boolean
double -> Double
2.常用API
void add(E e)
E remove(int index): 移除掉index位置的元素, 并返回
E get(int index)
int size()
3.: 泛型, 规定集合中元素的类型
没有规定泛型, 集合中的元素可以是任意类型
所以使用get()之类的方法时, 就不能确定返回值类型
所以, 使用集合时, 需要规定泛型
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("gggg");
list.add("hhhh");
list.add("dddd");
System.out.println(list);
String remove = list.remove(2);
System.out.println(remove);
System.out.println(list);
String get = list.get(1);
System.out.println(get);
int size = list.size();
System.out.println(size);
}
}
运行结果:
继承、super、this、抽象类
继承: extends
1.概念:子类/衍生类/扩展类: Dog
父类/基类: Animal
2.子类继承父类, 就继承了父类所有的成员变量和方法
3.所有的类, 都有唯一的父类,
如果没有写父类, 说明父类就是 Object
4.子类中还可以定义自己的独特的成员变量和方法
子类的功能一定比父类要强大
特殊情况:
1.子类中的成员变量和父类同名 name
Dog d = new Dog();
d.name -> 就是指自己定义的name,不是继承过来的name
结论: 父子类中的成员变量不要同名
2.子类中可以引用父类对象
super
3.创建子类对象之前, 会先创建父类对象
加载子类之前, 会先加载父类
4.构造方法: 父类的构造方法不能被子类继承的
创建子类对象, 会先默认调用父类的无参构造器
原因: 子类构造方法中, 第一行默认 super()
可以手动调用父类其他构造方法
结论: 子类构造方法中, 一定会先调用父类的构造方法
父类中, 建议先写无参构造器
5.通过子类对象调用方法时
先看子类中有没有定义这个方法, 定义了, 调用子类方法
子类中没有这个方法, 调用父类继承的方法
方法的重写\覆盖:
子类中定义的方法, 方法返回值类型\方法名\参数列表
都和父类中定义的方法完全一致
重写Override和重载Overload的区别
重写只存在于子类与父类中,重载存在于一个类中。
具体区别如下:
一、重写(override)
override是重写(覆盖)了一个方法,以实现不同的功能。一般是用于子类在继承父类时,重写(重新实现)父类中的方法。
重写(覆盖)的规则:
1、重写方法的参数列表必须完全与被重写的方法的相同,否则不能称其为重写而是重载.
2、重写方法的访问修饰符一定要大于被重写方法的访问修饰符(public>protected>default>private)。
3、重写的方法的返回值必须和被重写的方法的返回一致;
4、重写的方法所抛出的异常必须和被重写方法的所抛出的异常一致,或者是其子类;
5、被重写的方法不能为private,否则在其子类中只是新定义了一个方法,并没s有对其进行重写。
6、静态方法不能被重写为非静态的方法(会编译出错)。
二、overload是重载,一般是用于在一个类内实现若干重载的方法,这些方法的名称相同而参数形式不同。
重载的规则:
1、在使用重载时只能通过相同的方法名、不同的参数形式实现。不同的参数类型可以是不同的参数类型,不同的参数个数,不同的参数顺序(参数类型必须不一样);
2、不能通过访问权限、返回类型、抛出的异常进行重载;
3、方法的异常类型和数目不会对重载造成影响;
多态的概念比较复杂,有多种意义的多态,一个有趣但不严谨的说法是:继承是子类使用父类的方法,而多态则是父类使用子类的方法。
一般,我们使用多态是为了避免在父类里大量重载引起代码臃肿且难于维护。
继承是子类获得父类的成员,重写是继承后重新实现父类的方法。重载是在一个类里一系列参数不同名字相同的方法。多态则是用基类的引用指向子类的对象。
网上看到一个有趣的说法是:继承是子类使用父类的方法,而多态则是父类使用子类的方法。
下面的例子包含了这四种实现:
//Triangle 继承Shape类
class Triangle extends Shape {
//重写Shape类中的getSides方法
public int getSides() {
return 3;
}
}
//Rectangle 继承Shape类
class Rectangle extends Shape {
//重载Shape类中的getSides方法(在父类中getSide方法中添加了参数)
public int getSides(int i) {
return i;
}
}
//父类
public class Shape {
public boolean isSharp(){
return true;
}
public int getSides(){
return 0 ;
}
public int getSides(Triangle tri){
return 3 ;
}
public int getSides(Rectangle rec){
return 4 ;
}
public static void main(String[] args) {
Triangle tri = new Triangle();
System.out.println("Triangle is a type of sharp? " + tri.isSharp());
//isShape()为父类中的方法,Triangle中没有,所以tri.isSharp()方法为继承父类中的方法
Shape shape = new Triangle();
//new一个对象为Triangle的Shape实例(和new一个对象为dog的animal实例一样理解)
//此为父类的多态
System.out.println("My shape has " + shape.getSides() + " sides.");
}
}
比较就可以发现多态对重载的优点:如果用重载,则在父类里要对应每一个子类都重载一个取得边数的方法;如果用多态,则父类只提供取得边数的接口,至于取得哪个形状的边数,怎样取得,在子类里各自实现(重写)。
super 和 this
⽗类空间优先于⼦类对象产⽣
在每次创建⼦类对象时,先初始化⽗类空间,再创建其⼦类对象本身。⽬的在于⼦类对象中包含
了其对应的⽗类空间,便可以包含其⽗类的成员,如果⽗类成员⾮private修饰,则⼦类可以随
意使⽤⽗类成员。代码体现在⼦类的构造⽅法调⽤时,⼀定先调⽤⽗类的构造⽅法。理解图解如
下:
supert和this的含义
super :代表⽗类的存储空间标识(可以理解为⽗亲的引⽤)。
this :代表当前对象的引⽤(谁调⽤就代表谁)。
super和this的⽤法
- 访问成员
this.成员变量 -- 本类的
super.成员变量 -- ⽗类的
this.成员⽅法名() -- 本类的
super.成员⽅法名() -- ⽗类的
- 访问构造⽅法
this(...) -- 本类的构造⽅法
super(...) -- ⽗类的构造⽅法
⼦类的每个构造⽅法中均有默认的super(),调⽤⽗类的空参构造。⼿动调⽤⽗类构造
会覆盖默认的super()。
super() 和 this() 都必须是在构造⽅法的第⼀⾏,所以不能同时出现。
抽象类
由来
⽗类中的⽅法,被它的⼦类们重写,⼦类各⾃的实现都不尽相同。那么⽗类的⽅法声明和⽅法主
体,只有声明还有意义,⽽⽅法主体则没有存在的意义了。我们把没有⽅法主体的⽅法称为抽象
⽅法。Java语法规定,包含抽象⽅法的类就是抽象类。
定义
抽象⽅法:没有⽅法体的⽅法。
抽象类:包含抽象⽅法的类。
abstract使⽤格式
抽象⽅法
使⽤ abstract 关键字修饰⽅法,该⽅法就成了抽象⽅法,抽象⽅法只包含⼀个⽅法名,⽽没有
⽅法体。
定义格式:
修饰符 abstract 返回值类型 ⽅法名 (参数列表);
代码举例:
public abstract void run();
抽象类
如果⼀个类包含抽象⽅法,那么该类必须是抽象类。
定义格式:
abstract class 类名字 {
}
代码举例:
public abstract class Animal {
public abstract void run();
}
抽象的使⽤
继承抽象类的⼦类必须重写⽗类所有的抽象⽅法。否则,该⼦类也必须声明为抽象类。最终,必
须有⼦类实现该⽗类的抽象⽅法,否则,从最初的⽗类到最终的⼦类都不能创建对象,失去意
义。
代码举例:
public abstract class Animal {
public abstract void run();
}
public class Cat extends Animal {
public void run () {
System.out.println("⼩猫在墙头⾛~~~");
}
}
public class CatTest {
public static void main(String[] args) {
// 创建⼦类对象
Cat c = new Cat();
// 调⽤run⽅法
c.run();
}
}
输出结果:
⼩猫在墙头⾛~~~
此时的⽅法重写,是⼦类对⽗类抽象⽅法的完成实现,我们将这种⽅法重写的操作,也叫做实现
⽅法。
注意事项
关于抽象类的使⽤,以下为语法上要注意的细节,虽然条⽬较多,但若理解了抽象的本质,⽆需
死记硬背。
- 抽象类不能创建对象,如果创建,编译⽆法通过⽽报错。只能创建其⾮抽象⼦类的对象。
理解:假设创建了抽象类的对象,调⽤抽象的⽅法,⽽抽象⽅法没有具体的⽅法体,
没有意义。 - 抽象类中,可以有构造⽅法,是供⼦类创建对象时,初始化⽗类成员使⽤的。
理解:⼦类的构造⽅法中,有默认的super(),需要访问⽗类构造⽅法。 - 抽象类中,不⼀定包含抽象⽅法,但是有抽象⽅法的类必定是抽象类。
理解:未包含抽象⽅法的抽象类,⽬的就是不想让调⽤者创建该类对象,通常⽤于某
些特殊的类结构设计。 - 抽象类的⼦类,必须重写抽象⽗类中所有的抽象⽅法,否则,编译⽆法通过⽽报错。除⾮该
⼦类也是抽象类。
理解:假设不重写所有抽象⽅法,则类中可能包含抽象⽅法。那么创建对象后,调⽤
抽象的⽅法,没有意义。
简单补充
abstract: - 抽象的
抽象方法: 方法没有方法体
一个类中, 存在抽象方法, 那么这个类就必须也是abstract
抽象类: 用abstract修饰的类
抽象类不能直接new对象
有构造方法, 为了给子类使用
抽象类的非抽象子类, 必须实现/重写抽象类的所有抽象方法
判断:
1.有抽象方法的类叫抽象类 √
2.抽象类就是有抽象方法的类 ×
3.抽象类中可以没有抽象方法 √