要理解面向对象思想,我们先要知道什么是对象?
《Java编程思想》中提到“万物皆为对象”的概念。它将对象视为一种奇特的变量,它除了可以存储数据之外还可以对它自身进行操作。它能够直接反映现实生活中的事物,例如人、车、小鸟等,将其表示为程序中的对象。每个对象都具有各自的状态特征(也可以称为属性)及行为特征(方法),java就是通过对象之间行为的交互来解决问题的。
面向对象就是把构成问题的事物分解成一个个对象,建立对象不是为了实现一个步骤,而是为了描述某个事物在解决问题中的行为。
而类是从对象的属性和行为特征抽象出来的,对象是类的一个实例。比如说马,马是指一个概念,你可以具体到某一匹马,那么,这匹马就是马类的一个对象
创建类的格式
class 类名(首字母大写){
属性
方法
}
创建对象并给属性赋值,调用函数
类名 变量名 = new 类名(); 变量名.属性 = 变量; 变量名.方法();
class Person{
String name;
int age;
public void run(){
System.out.println("奔跑");
}
}
创建一个人的类,具有名字和年龄属性,还具有奔跑行为
public static void main(String[] args) {
Person per = new Person();
per.name = "里斯";
per.age = 18;
per.run();
}
在main方法中创建对象,并赋值,调用函数
一、类具有三大特征:封装,继承,多态 1.封装场景需求:试想一下,当你给一个对象赋值-5岁的时候,这在现实中是不可能的,但是在程序中是成功执行。
总结一下:核心思想就是“隐藏细节”、“数据安全”,将对象不需要让外界访问的成员变量和方法私有化,只提供符合开发者意愿的公有方法来访问这些数据和逻辑,保证了数据的安全和程序的稳定。所有的内容对外部不可见。
于是,我们将类的属性私有化(private),在内部进行处理,不允许外部通过赋值的方法进行修改,可以通过调用方法进行修改,方法内部进行一定处理,即可达到要求。
封装性的体现:
- Java规定的4种权限(从小到大排列):private、缺省(不加修饰符)、protected、public
- 4中权限可以用来修饰累计类的内部结构:属性、方法、构造器、内部类
修饰类的话,只能使用:缺省,public
封装举例
private int age;
public void setAge(int age){
if ( this.age >0 && this.age < 150){
this.age = age;
}else {
System.out.println("不符合要求");
}
}
定义变量age只有小于150大于0才能赋值成功
2.继承场景:有一个类有很多满足你的要求,你是要把这个类赋值下来吗?不需要赋值,使用继承,就拥有了他的大部分功能。
总结:子类可以继承父类的属性和方法,并对其进行拓展。将其他的功能继承下来继续发展 。
格式
class A extends B{}
A:子类,派生类,subclass
B:父类,基类,superclass
继承举例
public class Demo01 extends Person{
public static void main(String[] args) {
Demo01 de = new Demo01();
de.name = "li";
de.print();
}
}
class Person{
String name;
public void print(){
System.out.println(name);
}
}
注意:一旦父类A继承父类B以后,子类A中就获取了父类B中声明的所有的属性和方法。特别的,子类中声明为private的属性或方法,子类继承父类之后,仍然认为获取了父类中私有的结构,只有因为封装性的影响,使得子类不能直接调用父类的结构而已
规定
- 一个类可以被多个子类继承。
- Java中类的单继承性,一个类只能有一个父类
- 父子类是相对的概念。
- 子类继承父类之后,就获取了直接父类以及所有简介父类中声明的属性和方法
如果我没有显示的声明一个类的父类的话,则此类继承于java.lang.Object类
3.多态理解多态性:可以理解为一个事物的多种形态
何为多态性:对象的多态性,父类的引用指向子类的对象(或子类的对象赋给父类的引用)
多态性的使用前提:
- 类的继承关系
- 父类方法的重写
格式:父类类型 变量名=new 子类类型();
多态举例:
public class Demo01 extends Person{
@Override
public void print() {
System.out.println("Demo01");
}
public static void main(String[] args) {
Person per = new Demo01();
per.print();
}
}
class Person{
String name;
public void print(){
System.out.println(name);
}
}
虚拟方法调用(多态情况下):子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法成为虚拟方法,父类根据赋给它的不同子类对象,动态动用属于子类的该方法,这样的方法调用在编译器是无法确定的
运行时类型:在运行时才知道行为,例如随机数,只有运行时才知道是多少。
编译式类型:不运行就知道干啥
向下转型:有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法,子类特有的属性和方法不能使用.。因此可以把多态化的这个对象转为子类对象,调用子类属性和方法
首先构造器在创建类的对象时就出现了,就是类后面的括号。
用处:在创建对象时,初始化类的属性。
格式:权限修饰符 类名(形参列表){}
举例:
public class Demo01{
public static void main(String[] args) {
Person p1 = new Person("李四",18);
}
}
class Person{
String name;
int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
// 当初始化类信息之后,会覆盖原先的无参构造器,一般情况下,会重新协商
// 可以定义多个构造器,在调用时会根据参数不同调用不同的构造器,在一个构造器内部还可以调用其他构造器,在this中说明如何调用
public Person(){
}
}
注意:如果没有显示的定义类的构造器的话,则系统默认提供一个空参的构造器。当你自己创建有参构造器之后,会覆盖原先的无参构造器
三、this关键字用来区分类的属性与传进来的参数
格式:this.属性 = 形参
this调用构造器:
- 我们在类的构造器中,可以显示的使用“this(形参列表)”方式,调用本类中指定的其他构造器
- 构造器中不能通过“this(形参列表)”方式调用自己
- 规定:“this(形参列表)”必须声明在当前构造器的首行
- 构造器内部,最多只能声明一个“this(形参列表)”,用来调用其他构造器
举例:
class Person{
String name;
int age;
public Person(){};
public Person(String name){
this.name = name;
}
public Person(String name, int age){
// 调用其他构造器
this(name);
this.age = age;
}
}
四、super关键字
场景:当父类的方法被子类重写之后,还想要使用父类的这个方法,子父类出现同名的属性
super关键字的使用
- super理解为:父类的
- super可以用来调用:属性、方法、构造器
- 我们可以在子类的方法或构造器中,通过使用“super.属性”或“super.方法”的方式,显式的调用父类中声明的属性或方法。但是,通常情况下,我们习惯省略“super.”
- 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的使用“super.属性”的方式,表明调用的是父类中声明的属性。
- 特殊情况:当子类重写了父类中的方法以后,我们要想在子类中调用父类中声明的方法,则必须显式的使用“super.方法”的方式,表明调用的是父类中声明的方法。
举例
public class Demo01 extends Person{
public static void main(String[] args) {
Demo01 de = new Demo01();
de.print();
//父类的print
//子类的print
}
@Override
public void print() {
super.print();
System.out.println("子类的print");
}
}
class Person{
String name;
int age;
public void print(){
System.out.println("父类的print");
}
}
2.super调用构造器
- 我们可以在子类的构造器中显示的使用“super(形参列表)”的方式,调用父类中声明的指定的构造器
- “super(形参列表)”的使用,必须声明在子类构造器的首行
- 我们在类的构造器中,针对于“this(形参列表)”或“super(形参列表)”只能二选一,不能同时出现
- 在构造器的首行,没有显式的声明“this(形参列表)”或“super(形参列表)”,则默认调用的是父类中空参的构造器
- 在类的多个构造器中,至少有一个类的构造器中使用了“super(形参列表)”,调用父类中的构造器
当父类不存在空参构造器,而子类没有使用其他构造器时,就会报错
举例:
public class Demo01 extends Person{
char gender;
public Demo01(String name, int age, char gender){
// 调用父类构造器
super(name,age);
this.gender = gender;
}
}
class Person{
String name;
int age;
public Person(){};
public Person(String name, int age){
this.name = name;
this.age = age;
};
}
static关键字
用处:.static可以用来修饰:属性,方法,代码块,内部类。存在于方法区的静态域中
使用static修饰属性:静态变量属性,按是否使用static修饰,分为:静态属性和非静态属性(实例变量)
静态属性:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性,当修改其中一个对象中的非静态属性时,不会导致其他对象中同样的属性值的修改
静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量,当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改了的。
static修饰属性的其他说明:
- 静态变量随着类的加载而加载,可以通过”类.静态变量”的方式进行调用
- 静态变量的加载要早于对象的创建
- 由于类只会加载一次(创建完对象之后,会把类缓存到方法去),则静态变量在内存中也只会存在一份:存在方法区的静态域中
-
随着类的加载而加载,可以通过“类.静态方法”的方法进行调用
-
静态方法中,只能调用静态的方法或属性
非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性
举例:
public class Demo01{
public static void main(String[] args) {
// Person.name = "张三";
System.out.println(Person.name); // "张三"
Person.print();// "static"
Person p1 = new Person();
p1.name = "李四";
Person p2 = new Person();
System.out.println(p2.name); // 李四
}
}
class Person{
static String name = "张三";
int age;
static void print(){
System.out.println("static");
}
public void A(){
System.out.println("A");
}
}
static注意点
在静态的方法内,不能使用this关键字,super关键字
关于静态属性和静态方法的使用,大家都从生命周期的角度去理解
如何使用开发中,如何确定一个属性是否要声明为static?
属性是可以被多个对象共享的,不会随着对象的不同而不同的
开发中,如何确定一个方法是否要声明为static?
操作静态属性的方法,通常设置为static
工具类中的方法,习惯上声明为static。比如:Math,Arrays,Collections



