1.什么是面向对象
面向对象编程的本质:以类的方式组织代码,以对象的组织(封装)数据。
面向过程:
实现一个功能,每一个具体的步骤都要亲力亲为,详细处理每一个细节。
面向对象:
实现一个功能,不关心具体的步骤,而是找到一个已经具有该功能的人,帮我做事。
面向对象三大特性:封装,继承,多态。
1.封装,将数据封装在一个类,或者方法里;private关键字也是一种封装。
2.继承,子类继承父类的属性
3.多态,同一个事物有多种形态
2.类和对象的关系
1.类是对一类事物的描述,是抽象的。
2.对象是一类事物的实例,是具体的。
3.类是对象的模板,对象是类的实体。
比如生产手机之前,需要设计手机的设计图,设计图就是类,根据图纸生产出来的手机,就是对象。
3.类的定义
注意事项:
1.成员变量是直接定义在类当中的,在方法外边。
2.成员方法不要写static关键字。
4.对象的创建和使用
1.通过new关键字创建对象
比如: Student student = new Student();
解析: 类名 对象名 = new 类名();
类名()实际上是构造器
使用new关键字创建对象的时候,除了会分配内存空间外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
除了Java已有的内部类,其他非内部类需要先定义,在创建对象。
2.对象的使用
- 必须使用new关键字创造对象,构造器 Person fate = new Person();
- 对象的属性 fate.name
-对象的方法 fate.sleep()
5.构造器
类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。
构造方法的作用就是对 对象进行初始化的。(对对象中的属性赋值)
1.对对象属性初始化的方法:
a).通过set方法
b).通过构造方法 (建议多使用set方法初始化)
2.构造方法的语法:
修饰符 类名(参数列表) {
}
3.注意事项:
1.通过new 本质是在调用构造方法
2.用来初始化值
3.和类名相同
4.没有返回值
5.如果没有编写构造方法,那么编译器将会默认隐式的有一个无参的构造方法。
注意点:定义了有参构造之后,如果想使用无参构造,必须显式的定义个无参构造。
快捷键:alt+insert 生成构造器( constructor )。
this.属性 (this ,当前类)
6.对象-内存图
1.一个对象的内存图
2.两个对象使用同一方法的内存图
3.两个引用指向同一个对象的内存图
4.使用对象类型作为方法的参数
5.使用对象类型作为方法的返回值
7.成员变量和局部变量的区别
1.定义的位置不同(☆)
局部变量:在方法的内部
成员变量:在方法的外部,直接写在类当中。
2.作用范围不同(☆)
局部变量:只有在方法当中才可使用,出了定义局部变量的方法就不可在使用。
成员变量:整个类全都可以使用。
3.默认值不同(☆)
局部变量:没有默认值,如果想使用,必须先初始化(手动赋值)。
成员变量:如果没有初始化,会有默认值,规则和数组相同。
4.内存的位置不同(☆)
局部变量:位于栈内存。
成员变量:位于堆内存。
5.生命周期不同(☆)
局部变量:随着方法进栈而诞生,随着方法出栈而消失。
成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失。
8.private关键字的作用和使用方法
private就是将属性或者方法封装(隐藏)起来,阻止不合理的数值被设置进来。
解决:用private关键字将需要保护的成员变量进行修饰。
封装的作用:
提高程序安全性,保护数据,防止被设置不合理数据。
统一接口,使用接口来访问,隐藏信息
隐藏代码
增加代码的可维护性。
1.如果使用private进行修饰,在本类当中还可以使用。
但是如果超出本类范围,就不能在使用被private修饰的属性或者方法了。
(属性可以理解为变量)
2.使用private修饰的属性,需要定义Getter/Setter方法
使用public的get/set方法
get 获得属性
set 设置属性值
private String name; //定义私有变量
//set方法,返回值类型必须是void,因为它不需要返回数值
public void setName(String name){
this.name = name;
}
//get 方法,必须和私有变量的数据类型相同,因为需要返回相同类型的数值。
public String getName(){
return this.name;
}
调用:对象名.getName();
在IDEA中,可使用快捷键Alt+Insert快速创建get/set方法。
9.this关键字的作用
1.当方法的局部变量和类的成员变量重名时,根据就近原则,优先使用局部变量。如果需要访问本类的成员变量,就需要使用this。
格式:
this.成员变量名
this的值就是当前对象的首地址,也可以说这个this就是当前对象的一个引用,它指向当前new这个对象。
通过谁调用的方法,谁就是this
10.值传递和引用传递
首先,Java是值传递。
简单来说,
值传递,传的是一个真真切切的值,跟其他地方没有关联。
引用传递,传的是一个引用值,有关联性。
代码:
public class demo05{
//值传递方法
public static void test(int age){
age += 10;
System.out.println(age);
}
//引用传递方法
public static void test2(Pack pack){
pack.lock = 50;
}
public static void main(String[] args) {
//值传递
int age = 50;
System.out.println(age);
test(1000);
//引用传递
Pack pack = new Pack();
pack.lock = 20;
test2(pack);
System.out.println(pack.lock);
}
}
class Pack {
int lock;
}
11.匿名对象
什么叫匿名对象?
匿名对象就是没有引用地址的对象,如:
匿名对象:new Student();
普通对象: Student student = new Student();
什么时候要使用匿名对象?
- 不会调用对象的任何的成员变量,成员方法,直接进行对象的传递。
- 只对对象的成员进行一次调用时。(只使用一次)
12.static
说明1
静态的关键字是static,这个关键字可以修饰成员变量,成员方法,被static修饰的成员存储在JAVA内存中的静态方法区中,所有的对象都共享这块内存。
说明2
“static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”
这段话虽然只是说明了static方法的特殊之处,
但是可以看出static关键字的基本作用,简而言之,一句话来描述就是:
方便在没有创建对象的情况下来进行调用(方法/变量)。
很显然,被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。static可以用来修饰类的成员方法、类的成员变量,另外可以编写static代码块来优化程序性能。
- 什么时候要把一个成员变量用static进行修饰?
当一个类中的所有对象的某个属性的值都一样的话,那么我们常常把这个属性用static来修饰。 - 什么时候要把一个成员方法用static进行修饰?
当一个成员方法中没有使用到成员变量的话,就可以使用static来修饰这个方法。
注意: 静态方法中不能使用非静态的成员,为什么?
因为静态方法会先于非静态成员加载到内存中,我们如果使用静态方法时,很有可能静态方法中的非静态成员还没有初始化,所以我们不能在静态方法中使用非静态成员。
3.静态成员变量与静态成员方法的调用
a) 非静态成员调用
通过 “对象.成员名称”
b) 静态成员调用
1) 通过 “对象.静态成员名称”
2) 通过 ”类名.静态成员名称” (推荐)
4.静态成员变量与非静态成员变量的区别
- 存储区域
静态成员变量—》 静态方法区
非静态成员变量–》 堆内存 - 生命周期
静态成员变量–》类加载时开始初始化,类卸载时进行消毁。
非静态成员变量–》在堆内存中为对象开辟空间时开始进行初始化,当没有引用指向对象时,此时垃圾回收器会把非静态成员变量的内存空间消毁。 - 调用方式
静态成员变量-》可以通过类名,对象名来调用
非静态成员变量-》只能通过对象名来调用
5.静态代码块出现的原因:
对象初始化使用的方法是构造方法,如果对类进行初始化那么怎么办?
类中的初始化的意思是对类中的静态成员进行附值。
对象中的初始化的意思是对类中非静态成员进行的附值。
对静态成员不能用构造方法初始化的原因是因为,如果我们不去创建对象的话,那么静态成员就永远不会进行初始化了。
静态成员初始化可以使用静态代码块,静态代码块的语法如下:
static{
}
注意:一个类中可以有无数的静态代码块,它们的执行时机是随着类加载而执行的,它们的执行顺序时依照声明顺序来确定的。
静态代码块只能执行一遍,因为类只加载一次。
注意: static 不能修饰局部变量
6.执行顺序
先执行静态代码块
再执行构造代码块
再执行构造方法
13.继承
1.什么是继承?
1.继承是为了重用父类代码。
2.继承是多态的前提条件。
两个类若存在IS-A的关系就可以使用继承,同时继承也为实现多态做了铺垫。
继承的本质是对一些类的抽象,从而在父类的基础上实现更好的功能。
继承关系的两个类,被继承的是父类(基类),继承父类的是子类(派生类)。
子类继承父类,使用关键字extends来表示。
例子:
class Test extends Person {
}
注意事项:
1.被private修饰的类,无法被继承。
2.object是所有类的祖宗类
3.Java中只有单继承,没有多继承!
4.继承是类和类的一种关系,除此之外,还有依赖,实现,聚合等关系。
3.IDEA中ctrl+H 显示当前类的继承关系
14.super详解
super 父类
this 当前类
当子类继承父类,也会调用父类的构造方法(隐式或显式)。
子类继承父类的构造器时,super必须在第一行。
super注意点:
1.super 调用父类的构造方法,必须在构造方法的第一行
2.super 必须只能出现在子类的方法或者构造方法中!
3.super 和this不能同时调用构造方法!(调用时,必须在第一行,所以不管谁在第二行,都会报错)
注意:
代表的对象不同:
this: 调用当前对象
super :调用该类继承父类的对象
前提:
this:没有继承也可以使用
super:只能在继承条件下才可以使用
构造方法:
this();调用本类的构造;
super();调用父类的构造;
15.方法重写
非静态方法:重写
A a = new A();
静态方法: 方法的调用只和左边,定义的类有关
重写:需要有继承关系,子类重写父类的方法!
1.方法名必须相同
2.参数列表,列表必须相同
3.修饰符:范围,可以扩大:public >protected>Default>private,但不能缩小。
4.抛出的异常:范围,可以被缩小,但不能扩大:ClassNotFoundException --> Exception(大)
重写:子类的方法和父类必须要一致,方法体不同。
为什么需要重写?
1.父类的功能太多,子类不一定需要,或者不一定满足!
快捷键: Alt+Insert ; 选中override.
16.多态
1.多态的概念
(简而言之一句话:父类的引用,指向子类的对象。Parent p = new Child(); 😉
多态:实际类型确定,引用类型不确定,表现出来了多种状态,就是多态。
调用相同名字的方法,具体采用的是哪个方法,根据发送对象的不同而采用多种不同的行为方式,就是多态。
多态使程序更灵活。
比如:父类是Person,子类是Student,当:
Student s1 = new Student();
Person s2 = new Student(); //父类的引用指向子类
Object s3 = new Student(); //父类的引用指向子类
即:一个对象的实际类型是确定的,就是Student
但是,引用类型有指向Student的,有指向Person的,有指向Object的,引用类型不同。所以表现出了多种状态。
多态的注意事项
- 多态是方法的多态,属性没有多态。
- 父类和子类之间才有多态。当没有父子关系时,提示ClassCastExpection!异常。
- 存在条件:有继承关系,方法需要重写,父类引用指向子类对象(反过来不行,只能父类指向子类)。Father f1 = new Son();
多态的方法调用 - 一个对象的实际类型是确定的
1.1. new Student();
1.2. new Person(); - 可以指向的引用类型不确定:父类的引用可以指向子类
- Student(子类)能调用的方法是自己的,或者继承父类的
- Person(父类)和Object(父类)可以指向子类,但不能调用子类独有的方法。
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象! father f1 = new son();
- static 方法,属于类,不属于实例,不能被重写(static方法随着类的消失而消失)
- final 常量池,被final修饰的无法重写。
- private 方法 不能被重写。
结论:
1.对象能执行哪些方法,看对象左边的类型,与右边的关系不大。
2.对象执行的某一方法是类里面的方法,看等号右边,与前面相反。
解释下5中第一句话:子类有一个方法,父类没这个方法,父类 对象 = new 子类();则,该对象不能调用父类没有,子类有的这个方法。否则报错:
下面这个看等号左边:
解释下5中第二句话:子类有一个方法,父类没这个方法,父类 对象 = new 子类();则,该对象不能调用父类没有,子类有的这个方法。否则报错:
下面这个看等号右边:
总结:有没有方法看等号左边,执行哪个方法看等号右边(是否重写)
1、对于成员变量和静态方法,编译和运行都看左边。
2、对于成员方法,编译看左边,运行看右边。
2.类型转换
当父类中没有子类特有的方法,但是我们还想调用子类特有的方法就需要转换。
1.父类引用指向子类的对象
2.把子类转换为父类,向上转型;(会丢失方法)
3.把父类转换为子类,向下转型;(强制转换)
总结:方便方法的调用
类型之间的转换:
子类转父类(向上转型)
student extends person
Person obj = new Student();
父类转子类(向下转型,强制转换)
Person obj = new Student();
Student obj1 = (Student)obj;
父类转子类,可能会丢失一些自己的方法!
17.instanceof
instanceof 是 Java 的保留关键字。
它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
如果存在关系,则返回ture,如果不存在关系,返回flase
System.out.println(x instanceof y) 就是看x 引用指向的对象是不是y的子类。
说明:
(1).一个类的实例包括本身的实例,以及所有直接或间接子类的实例
(2).instanceof左边操作元显式声明的类型与右边操作元必须是同种类或有继承关系,
即位于继承树的同一个分支上,否则会编译出错
18.抽象类
abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
注意:子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
语法格式:
abstract class 类名{
public abstract void 方法名(){
}
}
抽象类的注意事项:
1.一个类中如果有抽象方法,那么这个类必须是抽象类。
2.不能new出来,只能靠子类继承去实现,约束!
3.一个类如果继承了一个抽象类,那么这个类必须实现抽象类中的抽象方法,如果不实现那么这个类也必须是抽象抽象类。
4.抽象类不可以产生对象。
5.抽象类中可以有构造方法,可以写普通方法
6.抽象类中的抽象方法不能与final关键字同用。
7.因为abstract关键字与final发生冲突,abstract意思是让子类来覆写方法,而final是不让子类覆写。
8.抽象类就是用来继承的,final修饰一个类代表着这个类不能被继承,所以也冲突了。
9.抽象方法不能用static来修饰。静态修饰的方法属于类的,它存在与静态区中,和对象就没关系了。 而抽象方法没有方法体,使用类名调用它没有任何意义。
10.private不能修饰抽象方法,因为私有的方法子类是无法继承到,也不存在覆盖,而abstract和private一起使用修饰方法,abstract既要子类去实现这个方法,而private修饰子类根本无法得到父类这个方法。互相矛盾。
关于构造方法与继承的问题?
1.构造方法可以被继承吗? 不可以被继承的。
2.构造方法可以被覆写吗? 不可以覆写的,因为不能继承。
3.抽象类中的构造方法有什么作用?是对抽象类中的成员变量进行初始化。
4.抽象类不可以产生对象,那么抽象类的构造方法怎么调用?
通过抽象类子类产生对象的时候调用。
19.接口
1.接口介绍
声明类的关键字是class,声明接口的关键字是interface。
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有
接口:只有规范,自己不能写方法,约束!(面向接口编程)
接口就是规范,定义的是一组规则,假如你是汽车,你必须能跑…
OO的精髓,对对象的抽象,最能体现的就是接口。
设计模式所研究的,实际上就是何如合理的去抽象。
interface 定义的关键字,接口都需要有实现类。
2.注意事项
1.抽象类:extends(只能实现单继承) 接口:implements(可以实现多继承)
2.接口中的所有定义其实都是抽象的 (可以不写public,会自动默认加public abstract)
3.接口没有构造方法,所以不能产生对象。
3.类 可以实现接口 (implements 实现接口的关键字。)
4.实现了接口的类,就需要重写接口中的方法~
5.在接口里定义的属性都是常量
6.接口中不能有具体方法
7.接口实现是like a
3.范例:
public interface UserService{
void run(String name);
}
public class UserServiceImpl implements UserService{ … }
4.接口的作用:
- 约束,定义规范。
- 定义一些方法,不同的实现方式, 10种实现方式 —> 1个接口(对程序进行扩展)
- 接口中的属性都是常量,可作为常量定义的集合。
- implements 可以实现多个接口
5.接口与抽象类的区别
- 接口中没有具体方法,所有方法都是抽象的,抽象类中可以有抽象和非抽象方法。
- 接口是多实现,抽象类是单继承。
- 接口中所有的方法隐含的都是抽象的。
- 类可以实现很多个接口,但是只能继承一个抽象类
- 类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。
- 抽象类可以在不提供接口方法实现的情况下实现接口。
- Java 接口中声明的变量默认都是 final 的。抽象类可以包含非 final 的变量。
- Java 接口中的成员函数默认是 public 的。抽象类的成员函数可以是private,protected 或者是 public 。
- 接口是没有构造方法,不可以被实例化。 抽象类也不可以被实例化,但是,如果它包含 main 方法的话是可以被调用的。
接口可以为类进行功能的增加
20.Java包和Jar包
1.Java的包
Java中的包的作用
- 解决类名冲突问题
- 方便对类进行分类管理
为类增加包的语法:
必须写在java文件的第一句:
package 包名;
注意:
3. 包名必须全部都是小写的
4. 包名一般来说的命名规则是比如公司
com.公司名.项目名.模块名.功能名
5. 如果有了包,一个类访问不同包中的类,就需要导包。(import 包名.类名; )
2.Jar包
一些java文件的集合,方便java文件的传输
也可以作为第三方包使用,去实现某些功能。
21.Java 四种权限修饰符访问权限
22.Java的内部类
说明
内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说称之为内部类,而A类相对B类来说是外部类。
注意:一个JAVA类中可以有多个class类,但是只能有一个public class
1.成员内部类
成员内部类就是在普通内部类中在定义类
1.成员内部类 - - 如何实例化内部类:
外部类的类名.内部类的类名 对象名 = new 外部类的类名().new内部类的类名();
注意:
- 如果在外部类的成员方法中建立内部类的对象时,我们不用再遵守上面的语法,直接进行实例化就可以了。
- 如果内部类在外部类以外的地方实例化的时候,我们必须依托外部类的对象产生内部类的对象。
- 普通类的权限修饰符只有public和默认权限修饰符,
- 如果是内部类的话,它可以使用任意权限修饰符(private 默认 protected public)
- 注意非静态内部类中不能定义静态成员变量和静态成员方法。但可以定义静态成员常量(final)。
- 原因常量在生成字节码文件时直接就替换成对应的数字。
当内部类在外部类成员位置上被私有修饰,在外部类以外的其他地方是无法访问的。只能在外部类中访问
2.静态内部类
静态内部类就是普通内部类用static修饰了
- 静态内部类实例化的方法
外部类的类名.内部类的类名 对象名 = new 外部类的类名.内部类的类名();
- 静态内部类不能够访问外部类的非静态的成员,但可以访问外部类静态的成员
3.局部内部类
局部内部类就是声明在方法中的类。
局部内部类中的方法如果访问包含它的外部方法的局部变量时,这个局部变量要求必须用final来修饰
注意:
当内部类在外部类的局部位置上时,这时在外部类以外的其他地方是无法创建局部内部类对象。
只能在内部类所在的局部方法中创建对象,通过外部类调用内部类所在的方法从而执行内部类中的方法。
匿名内部类就是内部类的简化形式。匿名内部类有前提,内部类必须要继承父类或者实现接口。
4.匿名内部类
匿名内部类:其实就是一个带有内容的子类对象。
格式:new 父类or接口(){子类的内容}
匿名内部类就是内部类的简化形式。
匿名内部类有前提,内部类必须要继承父类或者实现接口。