第三章 面向对象基础

https://blog.csdn.net/llwszjj/article/details/36451877

为了简单起见,只支持类之间的单继承,但支持接口之间的多继承,并支持类与接口之间的实现机制(关键字为implements)。

Java语言全面支持动态绑定,而C++语言只对虚函数使用动态绑定。(C++动态绑定:通过虚表实现动态绑定)

类和类之间具有一定的结构关系。        

继承:一般~具体        关联:整体~局部

面向对象的特征:唯一性(每个对象都是唯一的,自身具有唯一的标识,系统通过该标识可以找到相应的对象。)

分类性(分类性是指将具有一致属性和行为的对象抽象成类,只反映与应用有关的重要性质,而忽略其他一些无关内容。)

继承性

多态性(不同的对象,收到同一消息可以产生不同的结果,即具有不同的表现行为,这种现象称为多态性。)

将类定义成final后,结果只是禁止被继承——没有更多的限制

如果你把将score设为public,不用get()和set(),那么用户很可能会输入1-100以外的数字,如果你把将score设为private,再用setScore()来设置分数,你就完全可以控制这种行为了

Person p;//声明Person类型的对象p p= new Person();//使用new关键字创建对象,给对象分配内存空间

声明对象后,如果不想给对象分配存储空间

null赋给引用类型变量,但不可以赋给基本类型变量

类的成员变量具有默认初始值,整数类型的自动赋值为0,带小数点的自动赋值为0.0,boolean的自动赋值为false,其他各种引用类型变量自动赋值为null。

值传递时,实参和形参在内存中占不同的空间,当实参的值传递给形参后,两者之间将互不影响

在Java中,当参数的数据类型是引用类型时,如类、数组,实参和形参之间会是按引用传递的

当执行“Person p;”时,系统为引用类型变量p分配栈内存空间,此时只是定义了名为p的变量,还未进行初始化工作

执行语句“p = new Person("赵克玲",35,"青岛");”时,会首先在堆内存中创建一个Person类型的对象,并对各属性的值进行默认的初始化

一旦创建了自己的构造方法,缺省的构造方法将不复存在,上面的语句将无法执行。不过如果还想使用的话,则可以显式的写出来

方法重载:在同一个类中; 方法名相同; 参数列表不同,即参数的个数、或对应位置上的类型不同。不能将返回值类型的不同当成两个方法的区别

从JDK1.5之后,Java允许定义方法时参数的个数可以变化,这种情况称之为“可变参数”。

public int add(int a, int... b) {
	//......省略
}

1、可变参数只能处于参数列表的最后;

2、一个方法中最多只能包含一个可变参数;

3、可变参数的本质就是一个数组,因此在调用一个包含可变参数的方法时,既可以传入多个参数,也可以传入一个数组。

public static int add(int a, int... b) {
	int sum = a;
	// 可变参数b被当成数组进行处理
	for (int e : b) {
		sum += e;
	}
	return sum;
}

包:在Java中,我们使用package来解决名字冲突。

Java定义了一种名字空间,称之为包:package。一个类总是属于某个包,类名(比如Person)只是一个简写,真正的完整类名是包名.类名。

在定义class的时候,我们需要在第一行声明这个class属于哪个包。

package ming; // 申明包名ming

public class Person {
}

我们还需要按照包结构把上面的Java文件组织起来。假设以package_sample作为根目录,src作为源码目录,那么所有文件结构就是:

 编译后的.class文件也需要按照包结构存放。如果使用IDE,把编译后的.class文件放到bin目录下,那么,编译的文件结构就是:

包作用域

位于同一个包的类,可以访问包作用域的字段和方法。不用public、protected、private修饰的字段和方法就是包作用域。例如,Person类定义在hello包下面

缺省(包访问权限):如果一个类或类的成员前没有任何访问控制符,则获得缺省的访问权限,缺省的可以被同一包中的所有类访问;

package hello;

public class Person {
    // 包作用域:
    void hello() {
        System.out.println("Hello!");
    }
}

Main类也定义在hello包下面:

package hello;

public class Main {
    public static void main(String[] args) {
        Person p = new Person();
        p.hello(); // 可以调用,因为Main和Person在同一个包
    }
}

包的规范

一般采用域名的倒置,并且全部为小写,例如:www.baidu.com

为保证包名的规范性,建议以“公司域名反写.项目名.模块名”创建不同的子包,例如:com.qst.chapter03.comm包,“com.qst”是反写的公司域名,“chapter03”是项目名,“comm”是模块名。包名推荐使用倒置的域名,例如org.apache。

所以包就可以这样设置

什么时候把关系设置为继承?A is B 这时候就需要用到继承

对于类的调用者来说, protected 修饰的字段和方法是不能访问的

对于类的 子类 和 同一个包的其他类 来说, protected 修饰的字段和方法是可以访问的

protected(子类访问权限):被声明为protected的成员既可以被同一个包中的其他类访问,也可以被不同包中的子类访问;

class Test extends Animal{
public void func(){
Animal animal = new Animal();

System.out.println(animal.name);//错误!!这样调用时不行的

System.out.println(super.name);//正确,调用父类的需用到super关键字

}

}

 

final class A {}

这样子表示A这个类是一个密封类,代表当前类不可以被继承

super关键字

super和this经常一起被问到,

this代表当前对象的引用

先来说说this的几种方法

this() 调用自己的构造方法

this.func() 访问方法

this.data 访问属性

this 代表当前对象的引用

super 表示获取到父类实例的引用

子类继承了父类,子类构造的时候,需要首先帮助父类进行构造

怎么帮助构造,在子类的构造方法内部,调用父类的构造方法

super(); //显示调用父类的构造方法。所以,构造方法不是被继承的,而是在子类显示被调用的

class Animal {
public String name;

public int age;

public Animal1() {
}

public Animal1(String name){
}

public void eat() {
System.out.println(this.name + "::eat()");

}

}

class Dog extends Animal{
public Dog() {
super();

}

public Dog(String name) {
super(name);

}

}

注:super不能用在static方法中,因为static修饰的方法不借助任何对象,而super本身就代表父类对象的引用。

import

在一个class中,我们总会引用其他的class。例如,小明的ming.Person类,如果要引用小军的mr.jun.Arrays类,他有三种写法:

第一种,直接写出完整类名,例如:

// Person.java
package ming;

public class Person {
    public void run() {
        mr.jun.Arrays arrays = new mr.jun.Arrays();
    }
}

第二种写法是用import语句,导入小军的Arrays,然后写简单类名:

// Person.java
package ming;

// 导入完整类名:
import mr.jun.Arrays;

public class Person {
    public void run() {
        Arrays arrays = new Arrays();
    }
}

在写import的时候,可以使用*,表示把这个包下面的所有class都导入进来(但不包括子包的class):

// Person.java
package ming;

// 导入mr.jun包的所有class:
import mr.jun.*;

public class Person {
    public void run() {
        Arrays arrays = new Arrays();
    }
}

还有一种import static的语法,它可以导入一个类的静态字段和静态方法:

package main;

// 导入System类的所有静态字段和静态方法:
import static java.lang.System.*;

public class Main {
    public static void main(String[] args) {
        // 相当于调用System.out.println(…)
        out.println("Hello, world!");
    }
}

Java编译器最终编译出的.class文件只使用完整类名,因此,在代码中,当编译器遇到一个class名称时:

(1) 如果是完整类名,就直接根据完整类名查找这个class;

(2) 如果是简单类名,按下面的顺序依次查找:

查找当前package是否存在这个class;
查找import的包是否包含这个class;
查找java.lang包是否包含这个class。
如果按照上面的规则还无法确定类名,则编译报错。
 

// Main.java
package test;

import java.text.Format;

public class Main {
    public static void main(String[] args) {
        java.util.List list; // ok,使用完整类名 -> java.util.List
        Format format = null; // ok,使用import的类 -> java.text.Format
        String s = "hi"; // ok,使用java.lang包的String -> java.lang.String
        System.out.println(s); // ok,使用java.lang包的System -> java.lang.System
        MessageFormat mf = null; // 编译错误:无法找到MessageFormat: MessageFormat cannot be resolved to a type
    }
}

因此,编写class的时候,编译器会自动帮我们做两个import动作:

  • 默认自动import当前package的其他class;
  • 默认自动import java.lang.*。

小结
Java内建的package机制是为了避免class命名冲突;

JDK的核心类使用java.lang包,编译器会自动导入;

JDK的其它常用类定义在java.util.,java.math.,java.text.*,……;

package com.qst.chapter03;//定义多级包
1、package语句必须作为Java源文件的第一条非注释性语句;

2、一个Java源文件只能指定一个包,即只有一条package语句,不能有多条package语句;

3、定义包之后,Java源文件中可以定义多个类,这些类将全部位于该包下;

4、多个Java源文件可以定义相同的包。

类的静态变量和静态方法,在内存中只有一份,供所有对象共用,起到全局的作用。

实例化对象数组中的元素

array[0] = new Student("张三", "一年级2班", 90);

for (Student e : array) {// 遍历对象数组并输出   

 e.display();   

 System.out.println("------------------------");

猜你喜欢

转载自blog.csdn.net/qq_45598881/article/details/115566961