一:java面向对象的三条主线
*1. java类及类的成员:属性、方法、构造器、代码块、内部类
*
* 2.面向对象的三大特性:封装性、继承性、多态性、抽象性
*
* 3.其他关键字:this、super、static、final、abstract...
二:面向对象的一些基本知识
设计类,其实就是设计类的成员
* 属性= 成员变量 = field = 域、字段
* 方法 = 成员方法 = 函数 = method
*
* 创建类的对象 = 类的实例化 = 实例化类
*
*
* 类和对象的使用
* 1.创建类,设计类的成员
* 2.创建类的对象
* 3. 通过“对象属性或对象方法“调用对象结构
*
* //如果创建了一个类的多个对象,则每对象都独立拥有一套类的属性(非static的),
*
*
* 注意:局部变量不能使用权限修饰符
* 属性 vs 局部变量
*
* 不同点: 1.在类中声明的位置不同
* 属性:直接定义在类的一对{}内
局部变量:声明在方法内、方法形参,构造器形参,构造器内部变量
2.关于权限修饰符的不同
属性:可以在声明属性是,指明其权限,使用权限修饰符
常用的权限修饰符:private、public、缺省、protected ----》封装性
局部变量:不可以使用权限修饰符
3.默认初始化值
属性 :类的属性根据其类型,都有默认初始化值
整形:0
浮点型:0.0
字符型:0
布尔型:false
引用数据类型:null
局部变量:没有默认初始化值,
意味着在调用局部变量之前,一定要为其赋值
特别的:形参在调用时,我们赋值即可
4.在内存中加载的位置也不同
属性:加载到堆空间中(非static)
局部变量:加载到栈空间
三:关于java中方法的使用
方法的声明:权限修饰符 返回值类型 方法名(形参列表){
*
* 方法体
* }
*
*
* 返回值类型: 有返回值 vs 没有返回值
* 如果有返回值,则必须在声明时,指定返回值的类型。同时,
* 方法中需要使用return关键字来返回指定类型的变量或常量
*
* 如果方法中没有返回值,则方法声明时,使用void来表示,通常,没有返回值的方法中,就不使用return。但是,如果使用的话
* 只能 “return ;”表示结束此方法.
* 方法名:属于标识符
*
*
* return 关键字的使用
* 1:使用范围:使用在方法体中
* 2:作用:结束方法,
* 针对有返回值类型的方法,使用return 返回所要返回的数据
* 若返回值是数组类型的,则返回值为: return 数组名
*
* 3注意点:return关键字后面不可以声明执行语句
*
*
*
* 4.方法的使用:可以调用当前类的属性或方法
* 特殊的:递归方法
* 方法中,不可以定义方法
*
*
*
*
四:关于java中方法的重载
方法重载 :
* 1.在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者形参类型不同即可
*
* 两同一不同:同一个类,同一个方法名
* 参数列表不同,参数个数不同,参数类型不同
*
* 2。判断是否重载
* 跟方法的权限修饰符,返回值类型,形参变量名,方法体都没有关系
*
* 3.如何确定一个指定的方法
* 方法名---》参数列表
*
public class OverLoad {
//下面方法构成重载
public int max(int i, int j) {
return (i > j)? i : j;
}
public double max(double d1, double d2) {
return (d1 > d2)? d1 : d2;
}
public double max(double d1, double d2, double d3) {
double max = (d1 >d2)? d1 : d2;
return (max > d3)? max : d3;
}
}
五:方法中可变个数形参的使用
可变个数形参的方法
* 1.jdk 5.0的新特性
* 2.具体使用
* 2.1可变个数形参的格式:数据类型 . . . 变量名
* 2.2当调用可变个数形参的方法时,传入的参数可以是:0个 ,1个,2个
* 2.3可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载
* 2.4可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。换句话说,二者不能共存
* 2.5可变个数形参在方法的形参中,必须声明在末尾
* 2.6可变个数形参在方法的形参中,最多只能声明一个可变形参
*
public class MethodArgs {
public static void main(String[] args) {
MethodArgs margs = new MethodArgs();
margs.show(12);
margs.show("hello");
// margs.show(new String[] {"AA","BB","CC"});//通过数组来实现参数个数可变,匿名对象的使用
String[] strs1 = new String []{"AA","BB","CC"};
// margs.show("AA","BB","CC");
margs.show(strs1); //不通过匿名对象来使用
margs.show(1,2,3); //通过新特性来完成参数可变
}
public void show(int i) {
}
public void show(String s) {
System.out.println("show(String)");
}
public void show(int ...strs) { //如果是int型数据如何进行遍历
System.out.println("我是参数可变的重载方法");
//如何对其进行遍历
for(int i = 0; i < strs.length;i++) {
System.out.println(strs[i]);
}
}
public void show(String ... strs) {
System.out.println("我是string类型的可变类型方法");
for(int i = 0;i < strs.length;i++) {
System.out.println(strs[i]);
}
}
// public void show(String[] strs) {
// System.out.println("我是通过数组来实现参数可变");
// }
}
java中构造器的使用
一、构造器的作用:
* 1.创建对象
* 2.初始化对象的信息
*
*
*
* 二、说明
* 1.如果没有显示的定义类的构造器的话,系统默认提供一个空参的构造器
* 2.定义构造器的格式:权限修饰符 类名(形参列表){}
* 3.一个类中定义多个构造器,彼此构成重载
* 4.一旦我们显示的定义了类的构造器之后,系统就不在提供默认的空参构造器了
* 5.一个类中至少有一个构造器
*
*
* //总结;属性赋值的先后顺序
* 1.默认初始化值
* 2.显式初试化值
* 3.构造器中赋值
* 4.通过对象.方法或对象.属性,赋值
* 以上操作 的先后顺序 为:1-》2-》3-》4,其中前三步也被称为初始化
java中的传值一般规则
如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
* 如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值
*
*
*
*
* 重点: 方法形参的传递机制
*
* 形参:方法定义是,声明小括号内的参数
* 实参:方法调用时,实际传递给形参的数据
*
* 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值.
* 如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值
*
java中封装性的体现
我们将类的属性xxx私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)
*
* 拓展:不对外暴露的私有方法
*
* 三 、封装性的体现需要权限修饰符
* 1.Java规定了四种权限(从小到大) private、缺省、protected、public。
* 2.4种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类
* 3.具体的,4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类
* 修饰类的话,只能使用:缺省、public
*
*
* 总结封装性:Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小.
java中包的使用
一、package的使用
* 1.为了更好实现项目中类的管理,提供包的概念
* 2.使用package声明类或接口所属的包,声明在源文件的首行
* 3.包,属于标识符,遵循标识符命名规范、规范(xxxyyyzzz)“见名知意”
* 4.每“.”一次,就代表一层文件目录.
*
* 补充:同一个包下,不能命名同名的接口、类
* 不同的包下,可以命名同名的接口、类
*
*
* import关键字的使用
* import:导入
* 1.在源文件中显式的使用import结构导入指定包下的类、接口
* 2.声明在包的声明和类的声明之间
* 3.如果需要导入多个结构,则并列写出即可
* 4.可以使用“xxx.*”的方式,表示可以导入xxx包下的所有结构
* 5.如果使用的类或接口是java.lang包下定义的,则可以省略import结构
* 6.如果使用的类或接口是本包下定义的,则可以省略import结构
* 7.如果源文件中,使用了不同包下的同名的类,则必须至少有一个类需要以全类名的方式显示
* 8.使用“xxx.*”方式表明可以调用xxx包下的所有结构。但是如果使用的是xxx包下的结构,则仍需要显式导入
* 9.import static :导入指定类或接口中的静态结构.
*
*
*
* 所谓javaBean是指符合如下标注的java类
* >类是公共的
* >一个无参的公共构造器
* >属性,且对应的get、set方法
*
*/
java中this关键字的使用
this关键字的使用
* 1.this可以修饰:属性、方法、构造器
*
* 2.this修饰属性和方法:
* this理解为:当前对象 或 当前正在创建的对象
*
*
* 2.1 在类的方法中,我们可以使用“this.属性”或“this.方法”的方式,调用当前对象属性或方法。
* 但是通常情况下,我们都是选择省略“this.”。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用“this.变量”的方式,表名此变量
* 是属性,而非形参
*
*
* 2.2 在类的构造器中,我们可以使用“this.属性” 或“this.方法”的方式,调用当前对象属性或方法,但是通常情况
* 下,我们都选择省略“this.”。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用“this.变量”的方式,表名此变量是属性,而非形参
*
* 3.this调用构造器,通过构造器里调用构造器:主要是降低代码的冗余
* ①我们在类的构造器中,可以显式的使用“this(形参列表)”方式,调用本类中指定的其他构造器
* ②构造器中不能通过“this(形参列表)”调用自己
* ③如果一个类中有n个构造器,则最多有n-1个构造器使用了“this(形参列表)"
* ④规定:“this(形参列表)”必须声明在构造器的首行
* ⑤构造器内部,最多只可能声明一个“this(形参列表)”,用来调用其他构造器
*
关于java中的继承
一、继承的好处
* ①减少 了代码的冗余,提高了代码的复用性
* ②便于功能的扩展
* ③为之后多态性的使用,提供了前提
*
*
* 二、继承性的格式:class A extends B{}
* A:子类、派生类、subclass
* B:父类、超类、superclass
* 2.1体现:一旦子类A继承父类B以后,子类A中就获取父类B中声明的所有属性和方法
* 特别的,父类中声明的private的属性和方法,子类继承父类之后,仍然认为获取父类中私有结构。
* 只有封装性的影响,使得子类不能直接调用父类的结构而已
* 2.2 子类继承父类之后,还可以声明自己特有的属性或方法:实现功能的拓展
* 子类和父类的关系,不同于子集和集合的关系。
*
* 三、Java中关于继承性的规定:
* 1.一个类可以被多个子类继承
* 2.子父类是相对的概念
* 3.Java中类的单继承性:一个类只能有一个父类
* 4.子类直接继承的父类,称为:直接父类。间接继承的称为:间接父类
* 5.子类继承父类以后,就获取直接父类以及间接父类中声明的所有属性和方法
*
* 四、1.如果我们没有显式的声明一个类的父类的话,则此类继承与java.lang.Object类
* 2.所有java类(除java.lang.Object)都直接或间接的继承于java.lang.Object类
* 3.意味着:所有java类具有Java.lang.Object类声明的功能
*
java中的super关键字
super理解为:父类的
* super 可以用来调用:属性、方法、构造器
*
* 3.super的使用
* 3.1 我们可以在子类或构造器中。通过使用“super.属性”或“super.方法”的方式,显式调用
* 父类中声明的属性或方法.但是,通常情况下,我们习惯性省略“super”
*
* 3.2特殊情况:当子类和父类定义中定义同名的属性是,我们想要在子类中调用父类中声明的属性
* ,则必须显式的使用“super.属性”的方式,表名调用的是父类中声明的属性
*
* 3.3特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时
* ,则需显式的使用“super.方法”的方式,表名调用的是父类中被重写的方法
*
* 4.super调用构造器
* 4.1 我们可以在子类的构造器中显式的使用“super(形参列表)”的方式,调用父类中声明的指定构造器
* 4.2"super(形参列表)"的使用,必须声明在子类构造器的首行
* 4.3 我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二选一,不能同时出现
* 4.4 在构造器的首行,没有显式的声明“this(形参列表)”或“super(形参列表)”则默认调用的是父类中
* 的空参构造器.
* 4.5 在类的多个构造器中,至少有一个类的构造器中使用了“super(形参列表)”调用父类的构造器.
*
*
* *********************************************************************************
* 子类对象实例化的全过程
* 1.从结果上看:(继承性)
* 子类继承父类以后,就获取了父类中声明的属性或方法
* 创建子类的对象,在堆空间中,就会加载所有父类中声明的属性
*
* 2.从过程上来看
* 当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用父类的构造器,进而调用的父类
* 的父类的构造器.......直到调用了java.lang.Object类中的空参构造器为止。正因为加载过所有父类的
* 结构,所以才可以看到内存中有父类的结构,子类对象才可以考虑进行调用
*
*
* 明确:虽然创建子类对象时,调用了父类的构造器,但是自始至终就创建过一个对象,即为new的子类对象
*
*
java中方法的重写
方法的重写:1.子类继承父类以后,可以对父类中同名同参数的方法进行覆盖操作
* 2.应用:重写以后,当创建子类对象以后,通过子类对象调用父类中的同名同参数的方法
* 时,实际执行的是子类重写父类的方法
*
* 3.重写的规定:
* 方法的声明: 权限修饰符 返回值类型 方法名(形参列表){
* //方法体
* }
* 约定俗称:子类中叫:重写的方法 ,父类中的叫:被重写的方法
* ①子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
* ②子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
* >特殊情况:子类不能重写父类中声明private权限的方法
* ③ 返回值类型
* >父类被重写的方法返回值是void,则子类重写的方法的返回值类型只能是void
* >父类被重写的方法的返回值是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
* >父类被重写的方法的返回值是基本数据类型,则子类重写的方法的返回值必须是相同的。
* ④子类重写的方法抛出的异常不大于父类被重写的方法抛出的异常类型.
* *******************************************************
* 子类和父类中同名参数的方法要么都声明为非static(考虑重写)要么都声明static的(不是重写)
*
public class Interview {
public static void main(String[] args) {
Base1 base = new Sub1();//多态
base.add(1, 2,3);//子类重写了父类中的方法,所以此时执行子类中的方法 结果为:sub—_1
Sub1 s = (Sub1)base;//向下转型,可以调用子类中单独的方法
s.add(1, 2, 3); //输出结果为sub_2
}
}
class Base1 {
public void add(int a,int...arr) {
System.out.println("base1");
}
}
class Sub1 extends Base1 {
public void add(int a,int[] arr) {//子类重写了父类中的方法.
System.out.println("sub_1");
}
public void add(int a,int b,int c) {
System.out.println("sub_2");
}
}
java中的多态性
面向对象特征之三:多态性
* 1.理解多态性:可以理解为一个事务的多种形态
* 2.何为多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
*
* 3.多态性的使用 :虚拟方法调用
* 有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们时间执行的是子类重写父类的
* 方法
*
*
* 总结:编译,看左边 ;运行 ,看右边
*
* 4.多态性的使用前提 ①类的继承关系②方法的重写
*
* 5.对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
*
*
* 为什么super()和this()关键字都要声明在第一句
*
* 这是因为:无论通过那个构造器创建子类对象,需要先保证初始化父类。
* 目的:当子类继承父类字后,“继承”父类中所有属性和方法,因此子类有必要知道父类如何为对象进行初始化
/有了对象的多态性以后,内存中实际上是加载了子类所特有的方法和属性,但是由于变量类型声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能够调用
*
* 多态性的总结
*
* 1>在子类重写了父类的方法,就意味着子类定义的方法彻底覆盖了父类的同名方法
* 系统不可能把父类中的方法转移到子类中
*
* 2>对于实例变量则不存这样的情况,即使子类里定义了与父类完全相同的实例变量这个实例变量依然不可能
* 覆盖父类中定义的实例变量
*/
public class FieldMethodTest {
public static void main(String[] args) {
Sub s = new Sub();
System.out.println(s.count);//值 20:先在自己子类中找,没找到的话再去父类中找,就近原则
s.display(); //20
Base b = s; //多态把一个子类对象赋给父类引用,
System.out.println(b == s); //true:对于两个引用数据类型的变量比较的是地址池是否相等.
System.out.println(b.count); //因为多态只体现在方法上,而不体现在属性上(都看左边),所以值为:10
b.display();// 值20:因为子类和父类都有display这个方法,这个时候由于多态的原因,执行子类中的方法。
}
}
class 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);
}
}
关键字instanceof的使用
instanceof 前面的引用变量编译时的类型要么与后面的类型相同,要么与后面的类型具有父子继承关系(只能是其的子类)
如果a instanceof A 返回true ,则 a instanceof B 也返回true
其中B是A的父类
/要想向下转型能成功,一定不是new的父类对象,只能是new的子类的对象或间接子类的对象
其中Man的父类为Person类
// Person p5 = new Person();
// Man m5 = (Man)p5;相当于将父类直接转换为子类了。//因为子类中具有父类所不具的属性和方法,相当于是对父类的扩充,所以从这个角度来看
父类不能强转为子类,内存上不满足
// m5.earnMoney();
补充:
== 和equals()的区别
*
* 1.可以使用在基本数据类型变量和引用数据类型变量中
* 2.如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同)
* 如果比较的是引用数据类型的变量 :比较的是两个变量的地址池是否相等.即两个引用是否指向同一个对象实体
*
*二、equals方法的使用
* 1.是一个方法,而非运算符
* 2.只能适用于引用数据类型
* 3.Object类中equals()的定义:
* public boolean equals(Object obj){
*
* return (this == obj);
*}
*说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同,
*即两个引用是否指向同一个地址
*
* 4像String 、Data、File、包装类都重写了Object类中的equals()方法;重写以后比较的不是两个
* 引用的地址是否相同,而是比较两个对象的"实体内容"是否相同
*
* 5.通常情况下,我们自定义的类如果使用equals()的话。也通常是比较两个对象的“实体内容”是否相同.
* 那么我们就需要对Object类中的equals()进行重写.
*