---学习笔记(阿B韩顺平老师)
包
基本语法
package com.pak1;
1. package 关键字,表示打包
2. com.pak1 表示包名
包的导入:
1. import java.util.Scanner; //表示只会引入java.util 包下的Scanner
2. import java.util.*; //表示会引入java.util 包下的所有类
包的命名规则:与变量命名规则一样
包的命名规范:
com.公司名.项目名.业务模块名
举例:
1. com.sina.crm.user //用户模块
2. com.sina.crm.order //订单模块
访问修饰符
Java访问修饰符:
1. 公开级别: public ,对外公开
2. 受保护级别: protected ,对子类和同一个包中的类公开
3. 默认级别: 空, 向同一个包的类公开
4. 私有级别: private ,不对外公开,只有类本身可以访问
注意:
1. 成员方法和属性一样,如上表所示,四个修饰符都可以修饰
2. 类只有public 和 默认 能修饰
封装
介绍:封装(encapsulation)就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法],才能对数据进行操作。
封装的实现方法:
1. 将数据[属性]私有化(private),不能直接修改或访问属性
2. 提供一个公共的set方法,用于对属性判断并赋值:
public void setXxx(类型 参数名){
属性 = 参数名;
}
3. 提供一个公共的get方法,用于获取属性的值
public 类型 getXxx(){
return xxx
}
提示:上面步骤2、3可用快捷键 Alt + Insert 实现
封装与构造器
封装可以和构造器配合使用,具体操作就是在构造函数中去调用setXxx or getXxx
继承
前言:
继承可以解决代码复用,当多个类存在相同的属性和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需通过extends来声明继承即可。
基本语法
class 子类类名 extends 父类类名{
//子类会自动拥有父类定义的属性和方法
}
细节:
1. 子类继承了父类的属性和方法,但是父类中的私有属性和私有方法还是不能直接使用,而要通过公共的方法去访问。
2. 子类必须调用父类的构造器来完成父类的初始化
3. 当创建子类对象时,不管子类使用了哪种构造器,都会默认去调用父类的无参构造器,如果父类没有提供无参构造器,那么必须在子类的构造器中用super()来指定父类用哪个构造器来完成父类的初始化。
4. 如果希望指定去调用父类的某个构造器,则需要显式的调用一下。 super()
5. super() 和this() 都只能放在构造器的第一行,也就意味着,它们不能同时出现在一个构造器中。
6. Java中所有类都是Object类的子类。
7. 父类构造器的调用不限于直接父类,将一直往上追溯到Object类(“神父”,顶级父类)
8. Java中是单继承机制,也就是一个子类只能继承一个父类。但是父类也能继承属于它的父类,(谁没有个父呢)
细细节:
从父类、爷类、姥爷类等等寻找数据返回信息需遵守以下规则:
1.首先看子类是否有该属性,若有,并且可以访问,则返回信息
2. 若子类没有该属性,就看父类有无该信息,若有,并且可以访问,就返回信息
3. 若父类没有,就看爷类,看佬爷类,看佬佬爷类,指导Object类...
请注意:不管在哪”一辈“的类中查找到该属性,就算它不能直接访问(被私有化),也不会再往上查找了。
找方法和找属性规则一样。
super
首先注意区分super()、this()和super.xx 、 this.xx 的区别:
前者是调用父类和本类的构造器,并且只能出现在某个构造器的第一行。
后者是调用父类或本类的属性或方法。
当然,super.xx 和this.xx 调用方法规则与上面的细细节一样,只不过,super是从父类开始的。
另外,this.xx 等同与直接调用 xx ,(this并不局限于本类,若本类找不到,也是会向上查找的,与直接调用一个效果)
另另外,super.xx也不局限于父类,父类找不到的话,也会去爷类等去寻找。
方法重写
方法重写(覆盖)是子类有个方法,和父类的某个方法名称、参数、返回类型都一样,就是方法重写。(跟重载有些类似,不过是子类与父类之间的重名问题)
使用细节:
1. 子类的名称、参数要和父类的方法名称、参数完全相同。
2. 子类的返回类型也要和父类的相同,或者是父类返回类型的子类。比如:父类的返回类型是Object,子类的返回类型是String。(注意,Object类是一切类的基类)
3. 子类方法不能缩小父类方法的访问权限(访问权限:public > protected > 默认 > private)
多态
多态有方法多态和对象多态。方法多态从方法重载和重写就得以体现,下面主要说对象多态。
对象的多态
Animals animal = new Dog(); // 编译类型Animals 运行类型Dog,(Dog 是 Animals 的子类)
定义对象时,=(等号)左边时编译类型,=右边是运行类型。(javac-编译,java-运行)
1. 一个对象的编译类型和运行类型可以不一致。
2. 编译类型在定义对象时就确定了,不能改变。
3. 运行类型可以变化的。(向上转型)
向上转型
多态的前提:两个对象(类)存在继承关系。
本质: 父类的引用指向了子类的对象
语法: 父类类型 引用名 = new 子类类型(); // 就比如上面的 Animals animal = new Dog();
特点: 1. 左边编译类型,右边运行类型。
2. 可以调用父类的所有的所有成员(需遵守访问权限),
3. 不能调用子类的特有成员。(需要向下转型才可以)
对于2 和3 原因是因为在编译阶段,能调用哪些成员,是由编译类型决定的
4. 最终运行效果子类的具体实现,即调用方法时,按照从子类开始查找,然后调用的规则,就是前面所说的细细节规则。
向下转型
1. 语法: 子类类型 引用名 = (子类类型)父类引用;
2. 只能强转父类的引用,不能强转父类的对象;
3. 要求父类的引用必须指向的是当前目标类型的对象。
4. 可以调用子类类型中所有成员。
向下转型是为了调用那些子类中的特有成员。
“重写问题”
补充:关键字 a instanceof b, a是b的子类就返回true,否则返回false。
属性没有重写之说。 属性的值看编译类型,方法看运行类型。
看下面例题。
public class PolyExercise {
public static void main(String[] args) {
Sub s = new Sub(); //创建一个Sub对象s. s的编译类型Sub, 运行类型Sub
System.out.println(s.num); //200 输出s的属性num
s.display(); //200 调用方法
Base b = s; // b 的编译类型是Base 运行了类型是Sub
System.out.println(b == s); // true 因为b 和 s 指向的是同一个对象
System.out.println(b.num); // 100, 属性看编译,编译类型是Base,所以是Base类里面的num 100
b.display(); // 200 方法看运行,运行类型是Sub,从Sub类开始查找display方法
}
}
class Base{
int num = 100;
public void display(){
System.out.println(this.num);
}
}
class Sub extends Base{
int num = 200;
public void display(){
System.out.println(this.num);
}
}
动态绑定机制
1. 当调用对象方法的时候,该方法会和该对象的运行类型(内存地址)绑定。
2. 当调用对象属性时,没有动态绑定机制,哪里声明,使用哪里的属性。
看以下例题。当注释掉B类中的sum()方法和sum1()方法,结果又当如何。(30,20)
多态数组
数组的定义类型是父类类型,里面保存的元素可以是父类类型,也可以是各个子类类型。
其中Student和Teacher都是Person的子类
多态参数
方法定义的形参类型为父类类型,实参类型允许为子类类型。
Object类中的一些方法
equals 与 ==
== 可以判断基本类型和引用类型,判断基本类型时,判断值是否相等;判断引用类型时,判断地址是否相等,即判断是否为同一个对象。
而equals只能判断引用类型(equals是Object类中的方法),默认判断的是地址是否相等,但是子类经常会重写该方法(例如 String 类、Integer 类)
JDK查看源码
光标放上去,按快捷点ctrl + B
hashCode
xx.hashCode();
特点:
1. 提高具有哈希结构的容器的效率!
2. 两个引用,若指向的是同一个对象,则哈希值一定相同!
3. 两个引用,若指向的是不同对象,则哈希值是不一样的(也不绝对,但概率极低)。
4. 哈希主要是根据地址号得来的,但不能完全将哈希值等价于地址
toString
基本介绍:默认会返回: 全类名+@+哈希值的十六进制
子类往往会重写该方法 ; 全类名就是包名+类名。
快捷键 Alt + Insert 重写该方法,一般会输出该对象的属性值
当直接输出对象时,toString 方法会默认被调用。
Dog dog = new Dog();
System.out.println(dog); //直接输出对象。