面向过程编程与面向对象编程:
面向过程: 以过程为中心,实现功能的每一步都是都是自己去完成的
面向对象: 是一种以对象为中心的编程思想,指挥对象去完成具体功能的实现
以实际生活中做菜为类,面向过程的实现需要我们自己去买菜、然后洗菜、切菜再最后炒菜
面向对象的实现,只需要请一个厨师,由厨师去完成做菜
对象与类的关系:
世上万物皆对象,对象是肉眼能看见的具体事物,然后多个对象之间有共同的特征,抽象出共同特征划分为类。
先有对象,然后才有类,类是一种抽象概念并不是具体存在的事物
类是具有共同属性和行为对象的集合,就是对现实事物的一种描述
类的组成:
属性:事物的各种特征,也叫成员变量
定义格式 [权限修饰符] 数据类型 属性名 = [默认值] 属性名符合标识符的命名规则即可, 默认值可以不写,会自动为成员变量赋默认值
方法:事物的要执行的操作
定义格式 [权限修饰符] 返回值类型 方法名(参数列表){
//方法体具体实现的内容
}
堆内存(一种先进先出的数据结构):用来存放成员变量,以及new 出来的对象 ,由java的垃圾回收器回收,所有线程共享
栈内存(一种先进后出的数据结构):用来存放局部变量 和对象的引用,方法执行完成后自动释放空间,线程资源不共享
方法区:类的信息、static 修饰的变量 以及常量
局部变量和成员的区分:
作用:创建对象的时候会默认调用构造方法来创建对象,在堆中开辟空间,可以完成成员变量的某些初始化操作
无参构造方法:
访问修饰符 类名(){
// 初始化代码
}
有参构造方法:
访问修饰符 类名(参数列表 ){
}
注意事项: 构造方法的方法名必须跟类的名称保持一致
构造方法没有返回值,连void 都没有
构造方法可以进行重载,一个类中可以包含多个重名的构造方法
构造方法在每创建一次对象的时候,都会执行一次,不能手动调用
如果没有自定义构造方法的话,系统会默认生成一个无参构造方法一旦自定义构造方法之后系统的默认无参构造方法不在生效
推荐使用方式:为类提供无参构造方法 和有参构造方法
重载:在同一个类中可以包含多个重名的方法,但是注意方法的参数列表不能相同,参数个数不同,参数类型不同,参数顺序不同
this的作用:this表示的当前对象的本身,更准确的说代码的引用对象的指针,用于在构造方法中区分成员变量和局部变量重名问题
public Student(String username) { // 此处username 代表局部变量 并不是成员变量所以并不能进行初始化 username = username; }
在普通方法中使用this:
1.用来区分成员变量和方法的形参
在构造方法中可以this()来调用其他构造方法必须处于构造方法的第一行
public class TestThis { public int a,b,c; public TestThis(){ System.out.println("this 无参构造"); } public TestThis(int a){ this(); a = a ; // 此处a 是局部变量 this.a = a; } public TestThis(int a , int b , int c){ this(a); this.b = b; this.c = c; } public void play(){ System.out.println(this + "this play game"); } public void testPlay(){ play(); //this可以省略 } public static void main(String[] args) { TestThis t1 = new TestThis(1); //此时this 指向t1 TestThis t2 = new TestThis(1,3,4); //此时this 指向t2 System.out.println(t1.a); System.out.println(t2.b); t1.play(); t2.play(); } }
static 关键字是静态的意思,可以用来修饰成员变量和方法,修饰成员变量的时候,表示静态变量或者叫类变量,修饰方法的时候表示静态方法或者类方法
普通变量在使用的时候,必须要通过对象名调用
类变量在使用的时候,可以通过对象名调用也可以通过类名调用
静态方法既可以通过对象名调用也可以通过类名调用
注意
1.它为该类的公用变量,属于类,被该类的所有实例共享,在类被载入的时候显示初始化
2.静态变量的值被所有的对象共享,属于公共变量
3.成员变量存放在堆中,而静态变量放在方法中静态区
4.静态变量不能定义在方法里面
5.静态方法中不允许出现非静态变量和非静态方法,非静态方法不可以直接调用静态方法
6.静态方法中不能使用this关键字 静态方法归属于类,而this指向对象
一般工具类的方法定义为static
代码块:使用{} 括起来的一段代码
普通代码块 定义在普通方法中的代码块
构造代码块 定义在类中使用{} 括起来的代码块 每次代码运行的时候会将构造代码块的方法放在构造方法的前面,构造代码中的代码块会添加到每一个构造方法中,当使用this() 的时候不会添加
静态代码块 Static{} 括起来的代码块,在程序载入的时候优先执行 静态码块只执行一次
同步代码块:在多线程的时候会使用,用来给共享空间进行加锁操作
执行顺序: 静态代码块 ------构造代码块 ----- 普通代码块
public class TestCode { public String username; public int age; { System.out.println("构造代码块"); } public TestCode(){ System.out.println("无参构造"); } public TestCode(String username){ System.out.println("有参构造"); this.username = username; } public TestCode(String username, int age){ //this(username); this.username = username; this.age = age; System.out.println("有参构造"); } static { System.out.println("静态代码块"); } public static void main(String[] args) { TestCode t1 = new TestCode(); TestCode t2 = new TestCode(); } }
package包名对应于文件系统中就是目录,因为在同一目录下不能存在名字相同的文件,如果把所有的类文件都放在一个目录下不便于管理维护,可以安装分包(划分目录的思想)将要实现的功能类分类,包名的命名规则一般是公司域名倒写,字母都是小写
improt 导包 如果不导包的话,我们在使用其他包的类的时候我们就需要用包名.类名 这样会导致代码量过大
用法:import java.报名.类名
注意 java.lang 包是不需要手动导包的,比如String 、Math
封装的概念:
将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问
成员变量private,提供对应的getXxx()/setXxx()方法
对比于将成员变量的访问权限设为pubilic 而言可以直接修改属性值是不安全的。通过方法来控制成员变量的操作,提高了代码的安全性
把重复出现的代码用方法进行封装,提高了代码的复用性,减少代码的复杂度
java中访问权限修饰符
public : 公共的,当前项目所有类都可以访问
protected: 受保护的,可以被当前类访问,可以被当前包访问也可以被子类访问
Default: 可以被当前类访问和当前包访问
Private: 只能被当前类访问
注意四种访问权限修饰符只能修饰属性和方法
类的访问修饰符只有public 和 default 一个文件中只能有一个public 可以修饰类
类的属性一般使用private 并提供响应的get set 方法
为什么要使用继承:当多个类之间有相同的属性和行为的时候,可以将相同的属性和行为抽象出父类,子类继承父类之后可以使用父类中的属性和方法,也可以自己扩展。减少重复代码
继承的实现格式:
通过关键字extends 实现 class 子类名 extends 父类
继承特点:
super 关键字
1.super 是直接父类对象的引用,可以在子类用调用父类被子类覆盖的方法 super.父类方法名称
2.当super 在普通方法使用的话可以任意位置编写,当在构造方法中使用时,会调用父类的构造方法。一定要将super放在第一行
3.Super() 和 this() 不能同时存在
4.任何类的构造函数中,若是构造函数的第一行代码没有显示的调用super 那么java会默认的调用super() 作为父类的初始化函数。
5.子类的构造方法,会默认使用super 调用父类的无参构造方法,因此在定义类的时候,无论自己是否定义了其他构造方法,最好将无参构造方法写上
5.如果构造方法中显示的指定了super的构造方法,那么无参的构造方法就不会被调用
总结:
public class Person { private String name; private int age; public Person(){} public Person(String name, int age) { this.name = name; this.age = age; } public void test1(){ System.out.println("父类用来继承的方法"); } public void test2(){ System.out.println("父类用来拓展的方法"); } private void test(){ System.out.println("父类私有的方法"); } } public class Student extends Person { private int stuId; public Student(){ super(); } public Student(String name, int age,int stuId) { super(name,age); this.stuId = stuId; } public void test3(){ super.test2(); } public void test2(){ System.out.println("子类重写后的方法"); } public static void main(String[] args) { Student s1 = new Student(); s1.test1(); s1.test2(); s1.test3(); } }
方法重写:
当父类中的方法不满足子类的需求的时候,可以在子类中对父类中继承来的方法进行重写。重写方法必须和被重写的方法具有相同的方法名称,相同的参数列表以及返回类型
重写方法不允许比父类的方法具备更小的访问权限
静态方法可以被继承,但是不能被重写
Object类是所有类的父类
一个类如果没有使用extends显示的继承另外一个类 那么这个类就继承自Object类
Object类常用的方法
toString() // 输出对象名,如果不重写的话 默认输出类名加hashcode值 public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } hashcode() //返回对象的hash值 哈希表的数据结构,根据对象的地址值以及哈希算法一般除以膜取余 计算出对象在哈希表中的存储位置,因此两个对象值相同的话,hash值一定相同,哈希值相同则不能说明两个对象值相同 equals() //判断两个对象值是否相同 public boolean equals(Object obj) { return (this == obj); } == 号 与equals的区别 == 号用来比较两个基本类型的话,则比较基本类型的值是否相等 == 号用来比较引用类型的话,则比较引用类型的地址值是否相同 equals 如果类没有进行重写的话则比较地址值是否相等 但是如果进场重写了的话就需要根据重写后的方法进行比较比如String 重写equals 通常和重写hashcode一起重写
多态 是指同一个对象有多种不同的形态,既可以指向父类对象,也可以指向子类对象
为什么要使用多态:
假如两个子类都有相同的某个玩游戏的方法 ,再编写一个测试类分别去测试两个子类的玩游戏方法,需要定义两个方法,形参中分别传入两个子类对象,引入多态的话只需要在测试方法中定义一个方法,形参传入父类对象 然后再传入实参的时候父类对象的引用指向子类对象
多态形参具备的条件:
多态访问成员变量和成员方法的特点:
成员变量: 访问看父类的
成员方法:访问看子类的
向上转型和向下转型(结合数据类型的强转来看)
向上转型: 子类转换为父类,由小的范围变成大的范围,自动转型
向下转型: 由父类转换为子类,由大的范围变成小的范围,需要强转,在强转的过程中需要注意会出现classCastExpetion 需要结合 instanceof 来判断父类对象是否与子类对象一致