面向对象编程中级

IDE编程

常用快捷键

  1. 删除当前行,默认是ctrl+Y自己配置ctrl+ d
  2. 复制当前行,自己配置ctrl + alt+向下光标
  3. 补全代码alt+/
  4. 添加注释和取消注释ctrl+/【第一次是添加注释,第二次是取消注释】
  5. 导入该行需要的类先配置auto import ,然后使用alt+enter即可
  6. 快速格式化代码ctrl +alt + L
  7. 快速运行程序自己定义alt+R
  8. 生成构造器等alt + insert[提高开发效率]
  9. 查看一个类的层级关系 ctrl+H[学习继承后,非常有用]
  10. 将光标放在一个方法上,输入 ctrl+B,可以定位到方法[学继承后,非常有用]
  11. 自动的分配变量名,通过在后面假.var[老师最喜欢的]
    还有很多其它的快捷键...

基本语法

package 关键字,表示打包

包的本质是不同的文件夹/目录来保存文件

常用的包

一个包下,包含很多的类,java 中常用的包有:

  1. java.lang.* //lang 包是基本包,默认引入,不需要再引入.
  2. java.util.* //util 包,系统提供的工具包, 工具类,使用 Scanner
  3. java.net.* //网络包,网络开发
  4. java.awt.* //是做 java 的界面开发,GUI

引入包 import 包名;

  1. package的作用是声明当前类所在的包,需要放在类的最上面,一个类中最多只有
    一句package
  2. import指令位置放在package的下面,在类定义前面,可以有多句且没有顺序要求。

访问修饰符

java 提供四种访问控制修饰符号,用于控制方法和属性(成员变量)的访问权限(范围):

公开级别:用 public 修饰,对外公开

受保护级别:用 protected 修饰,对子类和同一个包中的类公开

重点:

受保护的访问修饰符-protected

protected 需要从以下两个点来分析说明:

子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问;

子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法。

// 示例一
package p1;
public class Father1 {
    protected void f() {
    }    // 父类Father1中的protected方法
}

package p1;
public class Son1 extends Father1 {
}

package p2;
public class Son2 extends Father1{
}

package p1;
public class Test {
    public static void main(String[] args) {
        Son1 son1 = new Son1();
        son1.f(); // Compile OK     ----(1)
        son1.clone(); // Compile Error     ----(2)
		

        Son2 son = new Son2();    
        son2.f(); // Compile OK     ----(3)
        son2.clone(); // Compile Error     ----(4)

		Test t = new Test();
		t.clone; // Compile OK
		// 测试类test只可以使用test类的继承Object类而来的test.clone()方法
    }
}

protected详解链接:https://blog.csdn.net/qq_37424916/article/details/107371305

默认级别:没有修饰符号,向同一个包的类公开.

私有级别:用 private 修饰,只有类本身可以访问,不对外公开

image

image

面向对象编程三大特征:封装

封装(encapsulation)就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作[方法],才能对数据进行操作。

1)隐藏实现细节:方法(连接数据库)<--调用(传入参数..)2)可以对数据进行验证,保证安全合理

封装的步骤:
将属性进行私有化private【不能直接修改属性】
提供一个公共的(public)set方法,用于对属性判断并赋值
public void setXxx(类型参数名)V/Xxx表示某个属性
//加入数据验证的业务逻辑
属性=参数名;
}
提供一个公共的(public)get方法,用于获取属性的值
public数据类型getXxx(){//权限判断,Xx某个属性
return xx;
}

将构造器和 setXxx 结合
 看一个案例
//有三个属性的构造器
public Person(String name, int age, double salary) {
// this.name = name;
// this.age = age;
// this.salary = salary;
//我们可以将 set 方法写在构造器中,这样仍然可以验证
setName(name);
setAge(age);
setSalary(salary);
}

继承:

继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。画出继承的示意图

image

继承的基本语法:
class子类extends父类{}
1)子类就会自动拥有父类定义的属性和方法2)父类又叫超类,基类。
3)子类又叫派生类。

代码的复用性提高了

代码的扩展性和维护性提高了

继承的细节

  1. 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问
  2. 子类必须调用父类的构造器, 完成父类的初始化
  3. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译 不会通过(怎么理解。) [举例说明]
  4. 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)
  5. super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)
  6. super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
  7. java 所有类都是 Object 类的子类, Object 是所有类的基类.
  8. 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)
  9. 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制。 思考:如何让 A 类继承 B 类和 C 类? 【A 继承 B, B 继承 C】 接口可以多继承
  10. 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系

继承的本质

//(1) 首先看子类是否有该属性

//(2) 如果子类有这个属性,并且可以访问,则返回信息

//(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)

//(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到 Object...

super关键字

super 代表父类的引用,用于访问父类的属性、方法、构造器

基本语法:

1.访问父类的属性,但不能访问父类的private属性[案例]
super.属性名;
2.访问父类的方法,不能访问父类的private方法
super.方法名(参数列表);
3.访问父类的构造器(这点前面用过):
super(参数列表);只能放在构造器的第一句,只能出现一句!

image

super和this的比较

image

方法重写/覆盖(override)

简单的说:方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法

image

image

多态:

方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。

多态的表现:1.方法的多态:重写和重载就体现多态

2.对象的多态

(1)一个对象的编译类型和运行类型可以不一致

(2)编译类型在定义对象时,就确定了,不能改变

(3)运行类型是可以变化的.
(4)编译类型看定义时=号的左边,运行类型看=号的右边

多态细节

多态的前提是:两个对象(类)存在继承的关系

image

java 的动态绑定机制(非常非常重要.)

image

多态的应用

多态数组 PloyArray.java 数组的定义类型为父类类型,里面保存的实际元素类型为子类类型 应用实例:现有一个继承结构如下:要求创建 1 个 Person 对象、2 个 Student 对象和 2 个Teacher 对象, 统一放在数组中,并调用每个对象 say 方法. 应用实例升级:如何调用子类特有的方法,比如 Teacher 有一个 teach , Student 有一个 study

public class PloyArray {
public static void main(String[] args) {
//应用实例:现有一个继承结构如下:要求创建 1 个 Person 对象、
// 2 个 Student 对象和 2 个 Teacher 对象, 统一放在数组中,并调用每个对象 say 方法Person[] persons = new Person[5];
persons[0] = new Person("jack", 20);
persons[1] = new Student("mary", 18, 100);
persons[2] = new Student("smith", 19, 30.1);
persons[3] = new Teacher("scott", 30, 20000);
persons[4] = new Teacher("king", 50, 25000);
//循环遍历多态数组,调用 say
for (int i = 0; i < persons.length; i++) {
//提示: person[i] 编译类型是 Person ,运行类型是是根据实际情况有 JVM 来判断System.out.println(persons[i].say());//动态绑定机制
//这里大家聪明. 使用 类型判断 + 向下转型. if(persons[i] instanceof Student) {//判断 person[i] 的运行类型是不是 Student
Student student = (Student)persons[i];//向下转型
student.study();
//小伙伴也可以使用一条语句 ((Student)persons[i]).study();
} else if(persons[i] instanceof Teacher) {
Teacher teacher = (Teacher)persons[i];
teacher.teach();
} else if(persons[i] instanceof Person){
//System.out.println("你的类型有误, 请自己检查...");
} else {
System.out.println("你的类型有误, 请自己检查...");
}
}
}
}

多态参数

方法定义的形参类型为父类类型,实参类型允许为子类类型

public class PloyParameter {
public static void main(String[] args) {
Worker tom = new Worker("tom", 2500);
Manager milan = new Manager("milan", 5000, 200000);
PloyParameter ployParameter = new PloyParameter();
ployParameter.showEmpAnnual(tom);
ployParameter.showEmpAnnual(milan);
ployParameter.testWork(tom);
ployParameter.testWork(milan);
}
//showEmpAnnual(Employee e)
//实现获取任何员工对象的年工资,并在 main 方法中调用该方法 [e.getAnnual()]
public void showEmpAnnual(Employee e) {
System.out.println(e.getAnnual());//动态绑定机制. }
//添加一个方法,testWork,如果是普通员工,则调用 work 方法,如果是经理,则调用manage 方法public void testWork(Employee e) {
if(e instanceof Worker) {
((Worker) e).work();//有向下转型操作
} else if(e instanceof Manager) {
((Manager) e).manage();//有向下转型操作
} else {
System.out.println("不做处理...");
}
}
}

object类

equals

image

hashCode方法

提高具有哈希结构的容器的效率!

两个引用,如果指向的是同一个对象,则哈希值肯定是一样的!

两个引用,如果指向的是不同对象,则哈希值是不一样的

哈希值主要根据地址号来的!, 不能完全将哈希值等价于地址。

案例演示[HashCode_.java]: obj.hashCode() [测试:A obj1 = new A(); A obj2 = new A(); A obj3 = obj1]

后面在集合,中 hashCode 如果需要的话,也会重写, 在讲解集合时,说如何重写hashCode()

toString方法

基本介绍 默认返回:全类名+@+哈希值的十六进制,【查看 Object 的 toString 方法】 子类往往重写 toString 方法,用于返回对象的属性信息

重写 toString 方法,打印对象或拼接对象时,都会自动调用该对象的 toString 形式.

案例演示:Monster [name, job, sal] 案例: ToString_.java

当直接输出一个对象时,toString 方法会被默认的调用, 比如 System.out.println(monster);就会默认调用monster.toString()

finalize方法(垃圾回收机制)

I)当对象被回收时,系统自动调用该对象的 finalize 方法。子类可以重写该方法,做一些释放资源的操作【演示】
2)什么时候被回收:当某个对象没有任何引用时,则jyvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize方法。
3)垃圾回收机制的调用,是由系统来决定(即有自己的GC算法),也可以通过System.gc()主动触发垃圾回收机制,

DEBUG调试

1.在开发中,新手程序员在查找错误时,这时老程序员就会温馨提示,可以用断点调试,
一步一步的看源码执行的过程,从而发现错误所在。
2.重要提示:在断点调试过程中,是运行状态,是以对象的运行类型来执行的.A extends B; Bb = new AO; b.xx();

1.断点调试是指在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,
然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。进行分析从而找到这个Bug
2.断点调试是程序员必须掌握的技能。
3.断点调试也能帮助我们查看java底层源代码的执行过程,提高程序员的Java水平。

F7(跳入)F8(跳过)
shift+F8(跳出)F9(resume,执行到下一个断点)
F7:跳入方法内
F8:逐行执行代码.shift+F8:跳出方法

posted @ 2024-01-14 17:57  十里-  阅读(18)  评论(0)    收藏  举报