5.包,面对对象的三要素
包
1.命名规则
只能包含数字、字母、下划线、小圆点、但是不能用数字开头,不能是关键字和保留字
2.命名规范
一般是小写字母+小圆点
一般是 com.公司名.项目名.业务模块名
比如:
com.sina.crm.user//用户模块
com.sima.crm.order//订单模块
com.sina.crm.utils//工具类
3.常用的包
1.java.lang.* //lang包是基础包,默认引入,不需要在引入
2.java.util.* //util包,系统提供的工具包,工具类,使用Scanner
3.java.net.* //net包,网络包,网络开发
4.java.awt.* //是做java的界面开发,GUI
例:用Arrays给数组排序
1 |
|
4.访问修饰符
用来控制方法和属性(成员变量)的访问权限(范围)
1.公开级别:用public修饰,对外公开
2.受保护级别:用protected修饰,对子类和同一个包中的类公开
3.默认级别:没有修饰符号,向同一个包的类公开
4.私有级别:用private修饰,只有类本身可以访问,不对外公开
访问级别 | 访问控制 | 本类 | 同包 | 子类(继承) | 不同包 |
---|---|---|---|---|---|
公开 | public | √ | √ | √ | √ |
受保护 | protected | √ | √ | √ | × |
默认 | 没有修饰符 | √ | √ | × | × |
私有 | private | √ | × | × | × |
注意事项: | |||||
1.修饰符可以用来修饰类中的属性,成员方法以及类 | |||||
2.只有默认的和public才能修饰类! | |||||
3.成员方法的访问规则和属性完全一样。 |
5.面向对象编程三大特征-封装
- 定义:把抽象出来的数据(属性)和对数据的操作(方法)封装在一起,数据被保护在内部,程序的其他部分只有同伙被授权的操作(方法),才能对数据进行操作。
封装的好处:隐藏实现细节 - 封装的实现步骤:
1.将属性进行私有化private[不能直接修改属性]
2.提供一个公共的set方法,用于对属性判断并赋值3.提供一个公共的get方法,用于获取属性的值1
2
3public void Set Xxx(类型 参数名){
属性=参数名;
}简而言之:封装就是利用get和set方法对传入的值可以加以判断,如果自己写了构造方法,则会绕过get和set方法,不能判断,所以可以这样写构造方法.1
2
3public 数据类型 get Xxx(){
return xx;
}1
2
3
4public Person(String name,int age){
setName(name);
SetAge(age);
}5.面向对象编程三大特征-继承
主要解决了两个类中的方法有很多是相同的。
关键字:extends
语法:class 子类 extends 父类。
继承的细节: - 子类继承了所有父类的属性和方法,但是私有属性和方法不能在子类直接访问,要通过公共的方法区访问。
- 当创建子类的对象时,不管使用子类的哪个构造器,默认情况下总会调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则编译错误。
- 如果希望指定去调用父类的某个构造器,则显式的调用一下:super(参数列表)。
- super()和this()都只能在构造器第一行,因此这两个方法不能共存在一个构造器。
super关键字
- 定义:super代表父类的引用,用于访问父类的属性、方法、构造器
- 当子类中有和父类中的成员(属性和方法),重名时,必须通过super+方法名。如果没有重名,则可以用this+方法名和super+方法名或直接访问是一个效果。注意:super可以跳过本类直接去找父类,如果本类有和父类一样的方法,则执行父类的方法。总而言之:子类和父类有一样的方法则系统会优先使用子类的,this和直接访问方式,如果使用了super+方法名则去访问父类的方法。
6.方法重写
名称 发生范围 方法名 形参列表 返回类型 修饰符 重载 本类 必须一样 类型,个数或者顺序至少有一个不同 无要求 无要求 重写 父子类 必须一样 相同 子类重写的方法返回的类型和父类返回的类型一致,或是其子类 子类方法不能缩小父类方法的使用范围 7.面向对象编程三大特征-多态
多态=多种状态
方法的多态:重写和重载就能体现多态
JAVA中的多态主要表现为方法的多态,主要是方法重载和方法重写的表现.
方法重载实现的是静态多态性,又称编译多态,在编译阶段确定调用哪个重载方法
方法重写实现的是动态的多态性,又称运行多态,在运行阶段确定调用哪个重载的方法
JAVA中方法的重载包括成员方法和构造方法的重载
对象的多态: - 一个对电工的编译类型和运行类型可以不一致
- 编译类型在定义对象时,就确定了,不能改变
- 运行类型是可以变化的
- 编译类型看定义时 = 号的左边,运行类型看 = 号的右边
例:
Animal animal = new Dog();
//animal编译类型是Animal,运行类型Dog;
animal = new Cat();
//animal的运行类型编程了cat,但编译类型还是Animal;向上转型:
多态的前提是:两个对象(类)存在继承关系
多态的向上转型 - 本质:父类的引用指向了子类的对象
- 语法:父类类型 引用名 = new 子类类型();
- 特点1:编译类型看左边,运行类型看右边
- 特点2:可以调用父类中的所有成员(遵守访问权限)
- 特点3:不能调用子类中的特有成员,最终运行效果看子类的具体实现。
例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35class Animal{
String name = "动物";
int age = 10;
public void sleep(){
System.out.println("睡");
}
public void run(){
System.out.println("跑");
}
public void eat(){
System.out.println("吃");
}
public void show(){
System.out.println("hello,你好");
}
}
class cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
public class test{
public static void main(String[] args){
Animal animal = new cat();//向上转型。
animal.xxx;//可以调用父类的所有方法(遵守访问权限),不能调用cat的catchMouse方法。
//不能调用子类的特有成员.(向下转型可以解决)
//因为在编译阶段,能调用哪些成员,是由编译类型决定的。
animal.eat();//输出猫吃鱼
//因为运行时,执行到该行时,animal运行类时cat,所以eat就是cat的eat
animal.run();//输出跑
}
}向下转型:
- 语法:子类类型 引用名 = (子类类型) 父类引用;
- 只能强转父类的引用,不能强转父类的对象
- 要求父类的引用必须指向的是当前目标类型的对象
- 当向下转型后可以调用子类类型中所有的成员
例:小细节:1
2
3
4//上例中的animal.catchMouse调用报错,可以用向下转型。
//语法:子类类型 引用名 = (子类类型) 父类引用;
Cat cat = (Cat) animal;//编译类型是cat,运行类型是cat。
cat.catchMouse();//即可调用。 - 属性没有重写之说!属性的值看编译类型。
- instanceOf比较操作符,用于判断对象的运行类型是否为XX类型或XX类型的子类型。
例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30class Base{
int count = 10;
public void display(){
System.out.println(this.count);
}
}
class Sub extends Base{
int count = 20;
public void display(){
System.out.println(this.count);
}
}
public class Test{
public static void main(String[]args){
Sub s = new Sub();//注意运行类型和编译类型,运行类型为Sub,编译类型为 Sub.
System.out.println(s.count);
s.display();
Base b = s;
System.out.println(b==s);
System.out.println(b.count);
b.display(); //注意运行类型和编译类型,运行类型为Sub,编译类型为 Base.
}
}
/*输出结果为:
20
20
True
10
20
*/8.JAVA动态绑定机制
- 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
- 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36class A{
public int i = 10;
public int sum(){
return geti()+10;
}
public int sum1(){
return i+10;
}
public int geti(){
return i;
}
}
class B extends A{
public int i = 20;
public int sum(){
return i + 20;
}
public int geti(){
return i;
}
public int sum1(){
return i+10;
}
}
public static void main(String[]args){
A a = new B();
//编译看左边,运行看右边
//a的编译类型A 运行类型B
//即调用的方法先看运行类型中有没有
System.out.println(a.sum()); //40
System.out.println(a.sum1()); //30
//如果把子类的sum方法注释,注意geti获得的值(调用的是子类的geti),此例中获得的是子类的geti的值,所以父类的sum方法为20+10=30。
/*
如果把B类的sum1方法注释,则执行父类的sum1方法,此时i的值为父类i的值,因为属性没有动态绑定机制。
*/
}9.多态数组
定义:数组的定义类型为父类型,里面保存的实际元素类型为子类类型。
例:现有一个继承结构如下,要求创建一个Person对象、2个Student对象和2个Teacher对象,统一放在数组中,并调用每个对象say方法。扩展:==和equals的对比1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80public class Person{
private String name;
private int age;
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
public String say(){
return name + "\t" + age;
}
}
public class Student extends Person{
private double score;
public Student(String name,int age,double score){
super(name,age);
this.score = score;
}
public void setScore(double score){
this.score = score;
}
public String getScore(){
return score;
}
//重写父类的say方法
public String say(){
return super.say()+ "score="+score;
}
}
public class Teacher extends Person{
private double salary;
public Teacher(String name,int age,double salary){
super(name,age);
this.salary=salary;
}
public void setSalary(double salary){
this.salary=salary;
}
public double getSalary(){
return salary;
}
}
//重写父类的say方法
public String say(){
return super.say() + "salary" + salary;
}
//主方法
public static void main(String [] args){
Person[] persons = new Person[5];
persons[0] = new Person("jack",20);
persons[1] = new Student("jack",20,100);
persons[2] = new Student("jack",20,30);
persons[3] = new Teacher("haozi",30,20000);
persons[3] = new Teacher("haozi",30,40000);
for(int i = 0;i<persons.length;i++){
//person[i]的编译类型是Person,运行类型是Perosn、Student、Teacher。
System.out.println(persons[i].say());//动态绑定
}
}
//升级:如果Teacher和Student类中都有一个自己的方法,则可以用向下转型。
/*
if(persons[i] instanceof Student){
Student student = (Student)person[i]//向下转型
student.study();
//一条语句执行:((Student)persons[i]).study;
}else if(persons[i] instanceof Teacher){
......
}
*/ - ==:既可以判断基本类型,又可以判断引用类型
- ==:如果判断及基本类型,判断的是值是否相等
- ==:如果判断引用类型,判断的是地址是否相等,即判定是不是同一个对象
equals方法(只能判断引用类型) - 默认判断的是地址是否相等,子类中往往重写该方法,用来判断内容是否相等,比如Integer,String
hashCode方法(后面会具体讲)
- 提高具有哈希结构的容器效率
- 两个引用,如果指向的是同一个对象,则哈希值肯定是一样的,否则哈希值是不一样的
- 哈希值主要是根据地址号来的,不能完全将哈希值等价于地址
toString方法:返回该对象的字符串表示 - 默认返回:全类名+@+哈希值的十六进制
- 重写toString方法,打印对象或拼接对象时,都会调用该对象的toString形式
- 直接输出一个对象时,toString方法会被默认调用
Finalize方法
- 当对象被回收时,系统会自动调用该对象的finalize方法。子类可以重写该方法,释放资源
- 垃圾回收机制的调用,是由系统来决定,也可以通过System.gc()主动触发垃圾回收机制
5.包,面对对象的三要素
http://example.com/2022/09/29/java/5.包/