面向对象
面向对象是一种编程思想,面向对象是基于面向过程思想,从面向过程思想演化过来的。
面向过程思想:关注过程。在完成功能的时候,里面的每一个细节,每一个步骤都需要我们自己亲力亲为去实现
面向对象思想:只关注结果。在完成功能的时候,不需要关注里面的细节,里面的细节是别人(对象)帮我们完成的。
简单来说面向过程思想自己做,面向对象思想别人做(坐享其成)
类和对象
类:对现实事物的一种描述,是抽象的(不具体的)。
对象:类的具体的体现
类的定义和使用(学生类)
定义
现实生活中描述某类事物,通常会通过两个方面去描述:属性和行为
属性:这类事物的一些特征;
行为:这类事物能做什么事情;
在类中,属性又被称为成员变量;行为又被称为成员方法.
成员变量:在类中方法外定义的变量;
成员方法:和之前的方法一样,只是去掉static关键字
使用
使用步骤:
1.导包(idea会自动导包)(两个类在同一个包,不需要导包)
2.创建对象
数据类型 对象名 = new 数据类型();//类是引用类型
3.使用成员
对象名.成员变量;
对象名.成员方法(参数);
注意:直接输出对象名,输出的是对象的地址
成员变量是有默认值的
类型 | 默认值 |
---|---|
byte,short,int,long | 0 |
float,double | 0.0 |
boolean | false |
char | ’ ’ |
引用类型 | null |
匿名对象
匿名对象就是没有名字的对象,如果在创建对象时仅仅把对象new出来了,但是没有用变量去接收这个对象,那么他就是匿名对象.
比如创建对象的格式:
数据类型 对象名 = new 数据类型();
比如上面代码只写右边,不写左边,他就是一个匿名对象:
new 数据类型();
好处:
稍微简化我们的代码
使用场景:
1.如果某个对象只需要使用一次,那么可以使用匿名对象;
2.匿名对象可以作为方法参数进行传递;
封装
封装是面向对象三大特征之一,另外两个分别是继承和多态.
封装思想的介绍:隐藏细节,提供对外界的访问方式。
在目前代码中的封装体现:
1. 将属性私有。 【隐藏细节】
2. 提供get和set方法。 【对外界的访问方式】
好处:
1.提高代码的安全性。
2.提高代码的复用性。
private关键字
private关键字:
1.是一个权限修饰符,表示私有;
2.可以修饰成员变量和成员方法;
3.被private修饰的成员只能在本类中使用;
成员变量被private修饰后,外界完全无法访问,这样也不好.我们需要提供一些方法,让外界去操作属性[赋值,取值]
getXxx和setXxx方法
this关键字
局部变量和成员变量的区别:
1.定义位置不同:
局部变量:方法中; 成员变量:类中方法外;
2.使用范围不同:
局部变量:作用域(离自己最近的一个{}); 成员变量:整个类中;
3.内存位置不同:
局部变量:跟随方法在栈内存中开辟; 成员变量:跟随对象在堆内存中开辟;
4.初始值不同:
局部变量:无默认值,使用前必须定义初始值; 成员变量:有默认值.整数是0,小数是0.0,字符是’ ',布尔是false,引用类型是null
5.生命周期不同:
局部变量:从方法执行到定义变量这行代码时产生,离开作用域后消失; 成员变量:随着对象的产生而产生,随着对象的消亡而消亡;
成员变量和局部变量允许重名:
如果重名,那么直接通过变量名访问到的是局部变量.
这时,我们可以用this关键字进行区分.使用this表示的是成员变量,格式:
this.成员变量名
this可以解决的问题:成员变量和局部变量重名
this 的含义:this表示本类对象,this所在的方法是通过哪个对象调用的,this表示的就是哪个对象.[真正保存的是这个对象的地址值]
构造方法
构造方法作用: 用来在创建对象的时候给属性赋值。
格式:
public 构造方法名(参数列表) {
构造方法体;
}
1. 构造方法不需要写返回值类型,连void都不用写
2. 构造方法名必须和类名一致
3. 构造方法不能return任何东西,但是单独写一个return是可以的, return一般省略。
构造方法的调用:
构造方法是在创建对象的时候自动调用的。
new 数据类型(); 这个操作是在创建对象, 此时就会调用构造方法。
在创建对象的时候小括号中我们可以传递一些参数, 程序会根据传递的参数调用对应的构造方法。
构造方法的注意事项:
1. 如果在一个类中我们没有给出构造方法,那么系统会帮我们提供一个空参数的构造方法。
2. 如果在一个类中我们给出了构造方法,那么系统就不会帮我们提供这个空参数的构造方法了。
3. 构造方法支持重载。
JavaBean的制作
Javabean规范
1. 将属性私有。
2. 提供get/set方法
3. 提供空参数的构造方法(必须),提供有参数的构造方法(选做,现阶段建议做)
标准学生类:
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
继承
Java中的继承是面向对象三大特征之一,另外两个分别是封装和多态。Java中的继承描述的是事物之间的所属关系。子类继承父类会自动拥有父类的成员(父类私有的成员也能继承,只是不能直接访问)
好处:提高代码复用性。
格式:
public class A {}
public class B extends A {}
上面代码表示B类继承了A类,B是子类,A是父类,B类会自动拥有A类所有的成员。
继承中成员变量的特点
继承关系中成员变量的访问特点:
通过子类访问成员,子类没有,会向上找父类。
通过父类访问成员,父类没有,不会向下找子类。
父类和子类成员变量同名时的访问特点(了解):
直接访问(通过子类对象直接访问):使用的是子类自己的成员。
间接访问(通过方法的方式去访问):调用的是哪个类中的方法,访问到的就是哪个类中的成员变量。
继承中成员方法的特点
继承中成员方法的访问特点:
如果子类中的成员方法和父类中的成员方法同名,那么通过子类对象访问成员方法,访问的是子类中定义的成员方法。
如果子类中出现了和父类一模一样的方法,那么这个就叫做方法的重写(override)。
重写和重载的区别:
重载: 同一个类中, 方法名相同,参数列表不同(参数的个数,类型,顺序不同)。
重写: 在子类中出现了和父类一模一样的方法。
方法重写
重写的注意事项
方法重写的注意事项:
1. 子类在重写父类方法时,参数列表必须相同。
2. 子类重写父类方法时,子类方法的权限一定要大于等于父类方法的权限【了解】
public > protected > 默认 > private
默认权限指的是省略不写,如果省略权限修饰符,那么方法就是默认权限。
3. 私有的方法不能被重写
方法重写的应用
如果父类的方法不能满足子类的需要,那么可以在子类中重写父类的方法。(新手机来电显示方法重写)
继承中的构造方法
在继承关系中构造方法的注意事项:
1. 构造方法不能继承。
2. 创建子类对象时会先执行父类的构造方法,然后执行子类的构造方法。 原因是因为在子类构造方法的第一句有一个隐藏的super(),是在调用父类的空参数构造方法
3. 我们也可以使用super关键字手动调用父类的构造方法. super(参数)
4. 如果使用super调用构造方法,那么只能放在第一行。
super的三种用途
super的三种用途
1. 可以访问父类的成员变量。 super.成员变量
2. 可以访问父类的成员方法。 super.成员方法()
3. 可以访问父类的构造方法。 super();
this的三种用途
this的三种用途:
1. 可以访问本类中的成员变量。 this.成员变量
2. 可以访问本类中的成员方法。 this.成员方法()
3. 可以访问本类中的构造方法。 this(参数);
如果this调用构造方法,也必须放在第一行
Java中继承的特点
1.Java中的类与类只支持单继承,一个类只能有一个父类。
2.Java支持多级/层继承,父类也可以有父类。
3.Java中一个父类可以有多个子类。
抽象类
抽象方法
如果一个方法的方法体,我们说不清道不明,不知道怎么写时,可以将该方法定义为抽象方法。
抽象方法:使用abstract修饰,没有方法体。
格式:
public abstract 返回值类型 方法名(参数);
抽象类的定义和使用
抽象类:抽象方法存在的类必须是一个抽象类。抽象类就是使用abstract修饰的类。
格式:
public abstract class 类名 {}
抽象类的使用:
1. 抽象类不能创建对象。
2. 抽象类是给子类用的,我们要定义一个子类去继承抽象类。
3. 子类继承抽象类重写抽象类中的所有的抽象方法。
4. 创建子类对象,通过子类对象调用方法。
抽象类的注意事项
抽象类的注意事项:
1. 抽象类不能创建对象
2. 抽象类中也是有构造方法的,抽象类中的构造方法是给子类用的。
3. 抽象类中可以有抽象方法,也可以有非抽象的方法。抽象方法所在的类必须是一个抽象类。
4. 一个普通类在继承抽象类时,必须重写这个抽象类中所有的抽象的方法。 一个抽象类在继承抽象类时,可以不重写抽象类中的抽象方法。
5. 抽象类的目的是为了让子类继承,体现的是模板思想。
抽象类的应用
新老司机开车(开门,点火,驾驶(新老司机不同),熄火,关门),可定义一个抽象司机类,其中固定的流程定义在父类中,不同的地方使用抽象方法,让子类继承重写。
public abstract class Driver {
//开车的方法
public void go() {
System.out.println("开门");
System.out.println("点火");
//驾驶
jiaShi();//真正执行的是重写后的该方法
System.out.println("熄火");
System.out.println("关门");
}
//定义驾驶的方法,因为不同的司机驾驶方式不一样,所以可以定义成抽象方法。
public abstract void jiaShi();
}
}
final关键字
final修饰类,方法,变量
如果final修饰类,这个类不能被继承,但是这个类可以继承其他类。
如果final修饰方法,这个方法不能被重写,但是可以被子类继承使用。
如果final修饰变量,这个变量的值不能被改变,从效果上看,这个变量也就变成了常量。
如果final修饰的是局部变量,那么变量的值只能赋值一次,一旦赋值就不能更改了。
如果final修饰的是成员变量,该变量也是只能赋值一次,一旦赋值不能更改。
final修饰的成员变量,必须在创建对象之前完成赋值(可以直接赋值,也可以构造方法中赋值)
常量的命名规范:所有字母都大写,如果有多个单词,多个单词之间使用下划线隔开。比如: AAA_BBB_CCC
final修饰引用类型的变量
如果final修饰引用类型的变量,那么是地址值不能变。因为引用类型的变量中保存的是对象的地址值。
static关键字
静态的介绍及基本使用
如果一个成员变量使用static修饰,这个成员变量就不再属于对象了,就属于类,会被该类的所有对象所共享。
被static修饰的成员,可以通过对象调用,也可以通过类名调用(推荐类名调用)
小结:
如果成员变量不使用static修饰,那么这个成员变量属于对象的,要有对象才能调用。
如果成员变量使用static修饰,那么这个成员变量属于类,可以通过类名调用.
静态方法的使用
如果一个方法使用static修饰了,那么这个方法属于类了,不属于对象,会被该类的所有对象共享。
静态方法和非静态方法的使用:
被static修饰的方法,可以通过对象调用,也可以通过类名调用,推荐类名调用。
没有被static修饰的方法,必须有对象才能调用。
调用同一个类中的静态方法,可以省略类名
静态的注意事项
静态的注意事项:
1. 静态方法中不能直接访问非静态成员。
静态属于类,非静态属于对象,有类的时候还没有对象呢,所以静态不能直接访问非静态。
2. 静态方法不能出现this和super
接口
接口的介绍
接口是一个规范(给类定义的规范, 类和接口发生关系后, 类要重写接口中的所有的抽象方法)
接口是一种引用数据类型。
接口的定义格式:
public interface 接口名{
}
接口编译之后也会生成.class的文件。
接口中可以有以下内容
在JDK7以及之前版本
1. 抽象方法(最核心)
2. 常量
在JDK8的时候
3. 默认方法
4. 静态方法
接口中抽象方法的定义和使用
接口中最核心的内容是抽象方法。
在任何版本的JAVA中,接口中都可以有抽象方法。
抽象方法的定义格式:
public abstract 返回值类型 方法名(参数);
注意:
1.接口中的抽象方法可以省略public abstract关键字。
2.如果接口中的抽象方法省略public abstract关键字,那么方法也是用public abstract修饰的。
接口中抽象方法的使用:
1. 接口不能创建对象。
2. 我们要定义一个类,使用这个类【实现】接口
3. 这个类要重写接口中的所有的抽象方法。
4. 创建这个类的对象,通过这个对象调用方法。
类实现接口的格式:
public class A implements I
上面代码表示A类实现了I接口. A类也叫I接口的实现类.
注意:
一个普通类实现接口时,必须重写这个接口中所有的抽象方法。
一个抽象类实现接口时,可以不重写接口中的抽象方法。
接口中的默认方法的定义和使用
在JDK8的时候,接口中可以有默认方法了。
默认方法定义格式:
public default 返回值类型 方法名(参数) {
方法体;
return 返回值;
}
注意:
1. 默认方法有方法体.
2. 默认方法中public关键字可以省略,如果省略该关键字,那么方法也是用public修饰的。
默认方法的使用:
1. 实现类在实现接口时可以不重写接口中的默认方法,我们可以通过实现类对象直接调用接口中的默认方法。
2. 如果接口中的默认方法不能满足实现类的需要,实现类也可以对默认方法进行重写。 实现类重写接口中的默认方法时,要去掉default关键字。
接口中静态方法的定义使用
在JDK8的时候,接口中可以有静态方法。
静态方法的定义格式:
public static 返回值类型 方法名(参数) {
方法体;
return 返回值;
}
注意:
1. 静态方法中public可以省略。
2. 如果省略public,那么该方法也是用public修饰的。
静态方法的使用:
接口中的静态方法要通过接口名字直接调用。
接口中定义的静态方法不能通过实现类去调用。
接口中常量
接口中可以有成员变量,从效果上看,这个成员变量就是常量。
在任何版本的JAVA中,接口中都可以有常量。
常量的定义格式:
public static final 数据类型 常量名 = 值;
因为使用final修饰了,所以值不能改变,所以我们把它叫做常量。
注意:
1. 接口常量中的public static final关键字可以省略
2. 如果省略public static final,接口中的常量也是用这几个关键字修饰的。
3. 接口中的常量因为使用static关键字修饰了,所以可以通过接口名直接调用。
4. 接口中的常量不能被改值。
5. 接口中的常量一定要给出默认值
6. 在给接口中的常量命名时,建议所有字母都大写,多个单词之间使用下划线隔开。
接口的多继承
类和类之间的关系是继承, 一个类只能继承一个类。
类和接口之间的关系是实现, 一个类可以实现多个接口。
接口和接口之间的关系是继承, 一个接口可以继承多个接口。
继承:extends
实现:implements
public interface A extends B, C {
}
上面代码表示A接口继承了B和C这两个接口。
注意:
如果多个父接口中出现了同名的抽象方法,没有影响的,抽象方法没有方法体,将来必须要重写,重写后的内容是什么,执行的就是什么。
如果多个父接口中出现了同名的默认方法,有影响的,在子接口中必须对默认方法进行重写。
一个类继承父类同时实现多个接口
一个类在实现继承父类的同时实现多个接口。
public class A extends B implements I1,I2{
}
上面代码表示A类继承B类的同时,继承了I1和I2两个接口.
注意:
如果父类中的方法和接口中的默认方法名相同,那么使用的是父类中的方法。
多态
多态的介绍
多态: 一个事物具备多种形态。
比如小明是一个学生,同时也是一个人,所以小明同时具备学生和人的形态,这个就是多态。
多态的代码体现(父类类型(变量,引用)指向子类对象):
父类类型 变量名 = new 子类类型();
接口多态(接口也可以看成一个特殊的父类)
格式(接口类型指向实现类对象):
接口类型 变量名 = new 实现类类型();
为什么父类类型可以指向子类对象:狗肯定是动物,所以可以把狗当成动物去看待,可以把狗赋值给动物类型。
注意:如果使用多态的方式创建对象,调用方法运行的是子类的方法(创建的是谁的对象,调用的就是谁的方法)
根据多态性,我们可以把子类类型当成父类类型去看待。(可以把狗当成动物去看待)
多态的好处
多态的好处:方法参数如果是父类类型,那么可以传递任何子类对象。
原因:
根据多态性,子类类型可以当成父类类型去看待。 比如狗可以当成动物去看待,因为狗肯定是动物。
所以参数如果需要动物类型(父类),那么我们可以传递狗对象(子类)
多态访问成员的特点
多态调用成员变量的特点【了解,不用】
编译看左边父类,如果父类中没有改方法,那么编译时期会报错。
运行看左边父类,真正使用的是父类的变量。
多态调用成员方法的特点。
编译看左边父类,如果父类中没有该方法,那么编译时期会报错。
运行看右边子类,真正运行的是子类的方法。
多态转型
引用类型的转换
向上转型:子类类型转成父类类型
父类类型 变量名 = new 子类类型();
向下转型:父类类型转成子类类型
子类类型 变量名 = (子类类型) 父类变量名;
注意:向下转型之前必须要有向上转型。
如果父类变量表示的对象不是要向下转型的目标类型,向下转型时会报错。(Animal类型的a表示的是Dog对象,但是却把a转成Cat)
多态的弊端:只能调用父类里面有的,不能调用子类特有的功能。
如果想要调用子类特有的方法,那么可以使用向下转型。
instanceof关键字
作用:可以判断某个变量表示的是否是该类型的对象。
格式:
变量名 instanceof 数据类型
举例:
a instanceof Dog 判断a是否是Dog类型
使用场景:
在向下转型之前使用instanceof关键字进行判断, 如果父类类型的变量表示的是要强转的子类对象,那么再向下转型。
内部类
成员内部类的定义和使用
如果将一个类定义在另一个类的里面,那么这个就是内部类。
里面的类叫做内部类,外面类叫做外部类。
如果将一个类定义在另一个类的成员位置(类中方法外),那么这个类就是成员内部类。
成员内部类的格式:
public class 外部类 {
public class 内部类 {
//内部类的成员
}
}
注意:
1. 内部类编译后也会生成.class文件。 格式为: 外部类$内部类.class
2. 内部类可以访问外部类的成员。
3. 外部类不能访问内部类中的成员
匿名内部类
匿名内部类是一种内部类,只不过这个内部类没有名字。
匿名内部类的作用:临时定义某个类的子类,创建该子类的对象。
匿名内部类的格式:
new 父类或接口() {
重写的方法
}
举例:
new Person() {
重写的方法
}
上面代码真正创建的是Person的子类对象,只不过这个子类叫什么,我们不知道,因为他是匿名的。
接口实现匿名内部类
使用接口实现匿名内部类,格式:
格式:
new 父类或接口() {
重写的方法
}
匿名内部类作为方法参数传递
public class Demo03Test {
public static void main(String[] args) {
//method方法参数是Animal类型,所以我们可以传递Animal子类对象。
//我们可以向method方法参数位置传递一个匿名内部类对象。
method(new Animal() {
public void eat() {
System.out.println("匿名内部类对象在吃");
}
});
}
/*
定义一个方法,可以让任何动物去吃
*/
public static void method(Animal a) {
a.eat();
}
}
权限修饰符
Java中的四大权限(public, protected,default,private)
public:公共的。 被public修饰的成员可以在任何位置使用。
protected:受保护的。 被protected修饰的成员可以在本包中,以及其他包下的子类中使用。(不能在其他包下的无关类中使用)
默认:默认的。默认权限的成员可以在本包中使用。
private:私有的。 被private修饰的成员只能在本类中使用。
权限修饰符表示的权限从大到小:
public > protected > default > private
最常用的两个:public private
代码块
构造代码块
格式:
{
构造代码块的内容;
}
定义位置:构造代码块要写在类的成员位置
执行时机:构造代码块会在每次创建对象的时候执行(优先于构造方法执行)
静态代码块
概念:使用static修饰的代码块。
格式:
static {
静态代码块的内容
}
定义位置:静态代码块也要定义在类的成员位置。
执行时机:静态代码块会在类加载的时候执行,终身只执行一次。
当我们第一次使用一个类时,这个类会加载到方法区,这个过程其实就是类加载。
静态代码块优先于构造代码块执行。
使用场景:
一些只执行一次的准备工作可以放在静态代码块中。 比如后期jdbc里面注册驱动。