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("------------------------");
}