一、匿名对象(没有名字的对象
- 只能调用一次
- 作用:往往作为实参进行传递
tips:给引用数据类型的变量赋值只能赋值该类型的对象。
二、方法重载
含义:在同一个类中,相同的方法名——不同的形参列表——构成方法的重载
形参列表不同:指形参的个数、类型、顺序不同;
tips:方法的重载与形参的名字、权限修饰符、返回值类型都无关。
如何确定调用的是哪个方法?——方法名 + (实参类型) 形参列表
public class OverloadTest{
public static void main{String[] args}{
}
//需求:求两数之和(不同数据类型
public void addInt(int a, int b){
}
public void addDouble(double a, double b){
}
......
//都叫 add 方法:
public void add(int a, int b){
}
public void add(double a, double b, int c){
}
}
三、可变形参
需求:求 5/6/30/356…个数的和
public void add(int ... numbers){//可变形参
tips:
- 可变形参的个数可以是一个或者多个
- 和可变形参相同类型的数组,不能构成重载(可变形参的底层就是一个数组)
- 可变形参只能作为最后一个形参;
- 在一个形参列表中,最多只能有一个可变形参。
public class VriableArgs{
public void add(int[] numbers){
int sum = 0;
for(int i = 0;i < numbers.length; i++){
sum += numbers[i];
}
System.out.println(sum);
}
//可变形参的个数可以是一个或者多个,格式如下:
public void add(int ... numbers){//可变形参
// ... numbers即数组——可变形参的底层就是一个数组
int sum = 0;
for(int i = 0;i < numbers.length; i++){
sum += numbers[i];
}
System.out.println(sum);
}
//可变形参不能有多个,只能最后一个是
public void add(int ... numbers, int ... numbers1){//报错
}
public void add(int ... numbers, int a){//报错
}
public void add(int a, int ... numbers){//这种正确!
}
public static void main(String[] args){
//创建对象
VriableArgs va = new VriableArgs();
int[] num = new int[]{1,2,3,4,5};
va.add(numbers);
va.add(new int[]{1,2,3,4,5,6,7,8});
//错误写法:
va.add({1,2,3,4,5,6});//必须对数组进行声明和初始化!
// (int ... numbers) 方式,如下代码正确:
va.add(1);
va.add(1,2,3,4,5);
va.add();//一个也不写,也可以通过。
}
}
四、值传递
下面三个案例,反映出基本数据类型和引用数据类型的不同:
在值传递的时候:
基本数据类型——传递(给)的只是值;
引用数据类型——传递的是地址——所以可以交换 m 和 n
下面这种方法可以实现交换——为啥????????——因为 int[] 是数组——引用数据类型
public class Swap0
{
public static void main(String[] args)
{
int[] i = {3, 5};
swap(i);
System.out.println(i[0]);
System.out.println(i[1]);
}
public static void swap(int[] a)
{
int temp = a[0];
a[0] = a[1];
a[1] = temp;
}
}
五、对象数组:数组中存储的是对象
class Computer{
String type;
}
public class ObjectArrayTest{
public static void main(String[] args){
String[] ps = new String[3];
ps[0] = "ccc"; //在Java中把所有双引号引起来的都看成是String的对象
ps[1] = new String("aaa");
Computer[] cs = new Computer[3];
System.out.println(cs[0]); //输出为 null
//1.向数组中存放对象
Computer c = new Computer();
c.type = "联想";
//2. 将对象放入数组中
cs[0] = c;
Computer s = new Computer();
cs[1] = s;
//通过获取数组中的元素给属性赋值
cs[1].type = "外星人";
}
public void demo1(){
//数组中的所有元素存储同一个对象时,指:新建一个对象,把它的地址值传给数组中的每个元素,这样修改一个,即同时修改了该地址指向的值,即修改了每个元素的值
//数组中所以元素存储不同对象的始向方式如下:
//创建数组
Computer[] cs = new Computer[3];
//给数组中元素赋值:每次都新建一个对象
for(int i = 0; i < cs.length; i++){
Computer s = new Computer();
cs[i] = s;
}
}
}
六、继承
面向对象特性之二:继承性
继承类中的属性和方法。
格式:
A extends B
A:子类,SubClass
B:父类,SuperClass,超类,基类
说明:
- 当一个子类继承一个父类后,子类就拥有了父类中的属性和方法
- 子类除了可以继承父类的属性和方法外,还可以定义自己的属性和方法(子类比父类更强大)
- 父类中的属性被私有化后,子类不能再直接访问父类中的该属性,但我们仍然可以通过间接的方式(set / get)进行调用。故我们还是认为子类继承到了该属性
- 构造器不能被继承。
- Java中的类是单继承,一个子类只能有一个父类。一个父类可以有多个子类。
- 子父类的关系是相对的。父类分为直接父类和间接父类(爷爷)。
- 当一个类没有显式继承其他父类时,默认继承 Object 类(Object类是所有类的父类)
继承的好处:
- 减少了代码的冗余
- 提高了代码的扩展性
- 为多态提供了前提
class Person{
String name;
int age;
private int sex; // private 可以被继承,但仍然是 私有的,不可被直接访问
public void info(){
System.out.println(name + " " + age);
}
public void setSex(int sex){
this.sex = sex;
}
}
class Student extends Person{
//String name;
//int age;
//class中声明了 extends Person ,就可以继承Person中的属性和方法了
int sid;
public void show(){
System.out.println(name + " " + age + " " + sid);
}
}
public class ExtendTest{
public static void main(String[] args){
Person person = new Person();
person.name = "echo";
person.age = 2;
Student student = new Student();
}
}
七、方法的重写
有了继承之后就可以考虑使用方法的重写。子类可以对父类的方法进行重写,覆盖原有代码。
使用场景:
如果子类对父类中的方法不满意,就可以考虑方法的重写。
说明:
当子类重写了父类中的方法后,那么再通过子类对象调用相同的方法,实际上调用的是子类重写父类的方法。
注意:
@Override
//加上这个注解,说明所注解的方法是一个重写的方法,如果不是(比如写错名字了)就会报错。
要点:
- 子类重写的方法的权限修饰符,不小于父类被重写方法的权限修饰符
- 子类重写的方法的方法名和形参列表必须和父类被重写方法的相同!
父类被重写的方法的返回值的类型 | 子类重写的方法的返回值类型 |
---|---|
void | void |
基本数据类型 | 对应的基本数据类型 |
引用数据类型 | 对应的类型、及子类的类型 |
比如:Object -> Number -> Interger (父类大,子类小)
- 子类方法抛出的异常不能大于父类被重写方法的异常
细节:
- 父类中被 private 修饰的方法,子类不能重写。
- 子类和父类中相同的方法,要么同时加 static 要么同时不加 static(不加就是方法的重写)
八、super关键字:
可以调用父类中的属性、方法、构造器。
调用属性、方法:
在子类的构造器和方法中可以使用 super 调用父类的属性和方法,但是我们可以省略 super;
如果子类和父类中的属性名相同或者子类重写了父类中的方法,那么必须使用 super来区分调用的是子类的还是父类的。
调用构造器:
作用:调用父类的构造器
格式:super(形参列表);
说明:
- super(形参列表);必须放在构造器的首行
- super(形参列表);和 this(形参列表);只能同时有一个
- 在子类的构造器中如果没有显式的使用 super(形参列表);和 this(形参列表);那么默认使用 super(形参列表);解决方式有两种:
- 父类提供一个空参构造器
- 子类中显式调用一个带参构造器
总结:
- 创建子类对象 必 调父类的构造器!!!
- this:先从子类中查找,如果有就调用子类中的,如果子类没有再调用父类的
- super:直接从父类中查找,如果父类中没有就直接报错
- 只要是调用父类中的属性和方法,全部加上 super