我们都知道面向对象他有三大特性
封装,继承,多态
接下来我会在一步步的讲解中,慢慢解释给大家
1.面向对象入门
当提到这个面向对象的时候,可能我们会是一头雾水,并且也不明白他有什么用。
那接下来咱用一个例子来解释一下;下面有个同学,他的名字叫小明,我们知道他的语文成绩,数学成绩,那我们怎么打印他的总成绩,和平均成绩呢
在以前,我们一般都会定义一个方法,然后调用方法来做,让我来给你写一下这个代码
这就是我们用定义方法然后,调用方法的办法来实现的
在上面的过程中,我们可以看到有三个数据,名字,语文成绩,数学成绩,这三个数据组成的一个对象,然后调用的方法也有这三个数据,这就是面向对象编程
同样是这样一个题目,我们用面向对象完全可以这样做
这样这个问题也解决了这就是面向对象编程
1.1深入了解面向对象
当我们了解了面向对象之后就会有几个问题,这样做有什么好处,然后程序中的对象是个啥,对象是怎么出来的?我们慢慢来解答;
这样做有什么好处,万物皆可对象,只要我们找到了对象就找到了,分析数据的入口,是我们的编程更加容易。
程序中的对象是什么;
就在刚刚那个题目中,我创建的s1就是一个对象,他就是 一种特殊的数据结构,咱们刚刚不是设置了三个数据,一个是名字还有语文成绩和数学成绩,我们创建了对象之后就会有三个空缺,当我们填上之后,就可以执行调用了,这就是对象。
对象是怎么出来的,这个问题就比较抽象了,在Java虚拟机的储存中,有栈和堆还有方法区
就是在我们创建对象的时候,我们的创建的student s1其实是存储在栈中,而我们new student()是在堆内存中开辟了一个空间然后给他了地址值,然后当student s1=new student();s1就会根据这个地址值找到我们定义的变量也就是对象,同理s2也是一样的
1.2注意事项
在前面的讲解中我们已经入门了,但是还是有几个注意事项,需要我们来说一下;
1.在一个代码文件中,可以写多个class,但是在public修饰的只能有一个而且名字必须是与文件名相同
2.对象与对象之间的数据不会相互影响,但是指向同一个数据就会发生影响了
我们先来对第一个注意事项来举个例子
两个的话他就报错咯
第二个其实很好理解;就是在那个题中;我们创建了s1,s2,有两个对象但是他们之间的数据是不会相互影响,但是如果你student s1 = s2;那么就会报错;
2,this关键字
this是什么,this其实就是一个变量;
我们记住一句话,就是哪个对象调用方法,方法中的this就是哪个对象
这两个地址值是一样的,所以就理解那句话了把哪个对象调用方法,this就代表哪个对象;
this有什么用呢
this他是可以调用成员变量的下面我们来用一个题目来解释一下
这样就很容易理解了吧,什么叫this关键字
3.构造器
我们只需要,掌握这几点构造器的知识就可以了
3.1什么是构造器
构造器其实是一种特殊的方法,他有空参构造,和有参构造两种,下面写一段代码来看一下就可以啦
这就是构造器也就做构造方法
3.2构造器的特点是什么
在创建对象的过程中会执行构造器,当构造器执行完毕之后,对象也就创建完毕了
下面还可以在()添加参数,但这是要在有有参构造器的时候才可以
3.3构造器是应用场景
构造器既然是用来创造对象的那么,它也可以添加对象的属性呀
3.4构造器的注意事项
他的注意事项其实也很简单
1.就是如果当我们没有定义构造器的是Java虚拟机会默认一个无参的构造器
2.当我们定义了一个有参的构造器时,Java虚拟机就不会默认给我们定义一个无参的了,建议我们自己定义一个
4接下来我们要学三大特性中的一个,封装
这个比较简单,我们可以想一想包装,我们是不是要把商品包装在袋子里面,这样商品是不是就不会被其他所影响
,这就是封装;在代码中是怎么体现的呢
用的就是private修饰符关键字,score就被封装到student这个类中,当你想对student对象赋值时,你只能使用Setscore来添加,赋值;接下来让我们来学习一个标准的JavaBean
5.JavaBean
什么是一个标准的JavaBean先让我们用代码演示一下
这就是一个标准的JavaBean
public class student {
String name;
int number;
int age;
public student() {
}
public student(String name, int number, int age) {
this.name = name;
this.number = number;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
我就直接来说几个比较重要的问题;
JavaBean的实体类是什么?
JavaBean的实体类是一种比较特殊的,他需要私有化成员变量,无产有参的构造方法,同时它还提供get和set方法
有什么特点?
他是对数据的一种封装,只用于取与存;
6.让我们来做一个题目来结束这一步入门的知识点吧
先定义一个JavaBean
public class Movie {
private int id;
private String name;
private double price;
private double score;
private String director;
private String actor;
private String info;
public Movie() {
}
public Movie(int id, String name, double price, double score, String director, String actor, String info) {
this.id = id;
this.name = name;
this.price = price;
this.score = score;
this.director = director;
this.actor = actor;
this.info = info;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public String getActor() {
return actor;
}
public void setActor(String actor) {
this.actor = actor;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
然后定义一个电影的操作类
public class MovieOperator {
//因为系统中有多部电影,所以电影操作类中,需要有一个Movie的数组
private Movie[] movies;
public MovieOperator(Movie[] movies){
this.movies = movies;
}
/** 1、展示系统全部电影信息 movies = [m1, m2, m3, ...]*/
public void printAllMovies(){
System.out.println("-----系统全部电影信息如下:-------");
for (int i = 0; i < movies.length; i++) {
Movie m = movies[i];
System.out.println("编号:" + m.getId());
System.out.println("名称:" + m.getName());
System.out.println("价格:" + m.getPrice());
System.out.println("------------------------");
}
}
/** 2、根据电影的编号查询出该电影的详细信息并展示 */
public void searchMovieById(int id){
for (int i = 0; i < movies.length; i++) {
Movie m = movies[i];
if(m.getId() == id){
System.out.println("该电影详情如下:");
System.out.println("编号:" + m.getId());
System.out.println("名称:" + m.getName());
System.out.println("价格:" + m.getPrice());
System.out.println("得分:" + m.getScore());
System.out.println("导演:" + m.getDirector());
System.out.println("主演:" + m.getActor());
System.out.println("其他信息:" + m.getInfo());
return; // 已经找到了电影信息,没有必要再执行了
}
}
System.out.println("没有该电影信息~");
}
}
然后就是test类了
public class Test {
public static void main(String[] args) {
//创建一个Movie类型的数组
Movie[] movies = new Movie[4];
//创建4个电影对象,分别存储到movies数组中
movies[0] = new Movie(1,"水门桥", 38.9, 9.8, "徐克", "吴京","12万人想看");
movies[1] = new Movie(2, "出拳吧", 39, 7.8, "唐晓白", "田雨","3.5万人想看");
movies[2] = new Movie(3,"月球陨落", 42, 7.9, "罗兰", "贝瑞","17.9万人想看");
movies[3] = new Movie(4,"一点就到家", 35, 8.7, "许宏宇", "刘昊然","10.8万人想看");
}
}
// 4、创建一个电影操作类的对象,接收电影数据,并对其进行业务处理
MovieOperator operator = new MovieOperator(movies);
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("==电影信息系统==");
System.out.println("1、查询全部电影信息");
System.out.println("2、根据id查询某个电影的详细信息展示");
System.out.println("请您输入操作命令:");
int command = sc.nextInt();
switch (command) {
case 1:
// 展示全部电影信息
operator.printAllMovies();
break;
case 2:
// 根据id查询某个电影的详细信息展示
System.out.println("请您输入查询的电影id:");
int id = sc.nextInt();
operator.searchMovieById(id);
break;
default:
System.out.println("您输入的命令有问题~~");
}
}
这样就可以啦
7.然后就是成员变量和局部变量
目前来说我们这一部分学的最重要的地方就是封装,可以好好理解一下;
2.面向对象中级
然后现在我们来学习面向对象进阶,来看看他这是怎么个事
1.静态--static
之前说过static他是一个关键字,而且他是一个在面向对象中比较重要的关键字
看看他有什么作用
1.1静态变量与实例变量
什么叫静态变量,被static修饰的变量就是静态变量,然后没有别修饰的就是实例变量,来个代码看看就明白了;
在这里面name就是静态变量,而age就是实例变量;
然后既然是面向对象的里的变量,就肯定会被,创造的对象,添加数据,但是静态数据变量不一定
特点:
静态变量,他是在类中的,在本类中所共享,而实例变量,他是对所有对象所共享,
也就是说当我给那个name赋值之后,创建的所有变量name全为name,而age可以每个对象不同而更改
来个图比较直观的表达一下
就是和上面的图的意思一样
由于静态变量是属于类的所以要,用类名而调用,就是这样类名,静态变量(也可以用对象名,静态变量,不推荐)
而实例变量是属于对象的,所以要,用对象名而调用,也就是这样的 对象名,实例变量
你会发现这个样idea会给你黄线,这是不推荐的
我们可能会有疑问为什么不推荐这就来给你解释
看上面,我们想要的明明是t1叫小王,t2叫小张,可是这个样子都成小张了,这就是不推荐的理由;
1.2static静态的应用场景
当我们学了这一种关键字之后,我们就会有疑问,这东西的应用场景是什么呢,该怎么想呢,这就来了
就比如在实际的开发中,当我们的数据中有一份数据,需要全员共享,并且全员访问和修改那么静态就上线了;
**我们看一个案例****
需求:系统启动后,要求用于类可以记住自己创建了多少个用户对象。**
这样不就出来了吗,就比较简单
1.3静态成员方法与实例方法
有静态变量就有静态方法,同样用static修饰的成员方法就是静态成员方法,没有的就是实例成员方法
调用的时候还是一个样子:推荐:类名,静态成员方法
实例方法的调用就是:对象名,实例成员方法
对象名,静态成员方法都直接报错了,就别用了
就是这个样子;
1.4工具类
大家可能都听到过工具人,是不是哪里需要哪里搬,工具类也是一样,联想到上面说的静态修饰的属于整个类,所以当这一整个类都被static修饰时,这个类里面的方法什么的就可以哪里需要哪里搬了,和一个工具一样就叫做工具类;
来个代码演示一下
这就是工具类的使用方法你明白了吗?
补充一点,因为工具类中的方法都是静态的,需要我们用类名调用,而不是对象名,所以我们可以将构造方法私有化,这样可以防止对象名无法调用了;
1.5注意事项
1.在类中静态方法,可以访问类的成员,但是实例方法与实例对象无法访问;
2.但是在实例方法中,可以访问类的成员,也可以访问实例成员
3.this在实例成员中可以使用,但是在静态中无法使用
2.继承
然后让我们来学习学习一下面向对象三大特征的第二大特征,继承
2.1什么叫继承
这东西不理解的话就举个例子,当有一个富豪,他去世了,那他天大的遗产怎么办,是不是继承给他的儿子或者女儿,这就是继承,他有子类与父类,子类继承了父类的变量和方法(私有化除外)
他的关键字是extends
也就是说B能能继承A中变量和方法(私有化除外),子类的对象由子类与父类共同完成。
可以看到确实不能调用私有化的变量和方法
这就是继承;
这是他们的内存图
2.2继承的好处
继承的好处很简单,就是提高了代码的复用性,减少了代码重复度
2.3权限修饰符
咱在前面已经就是讲过了
权限修饰符三种private私有化,public共有化,protest保护,还有就是省略不写
再来说一下
权限修饰符 | 在同一类中 | 在同一包的不同类中 | 在同一包的子类中 | 在任意包的任意类中 |
private | yes | |||
public | yes | yes | yes | yes |
protect | yes | yes | yes | |
省略不写 | yes | yes |
2.4单继承和多重继承,object
单继承就一个子类继承一个父类,而多重继承就是你有爸爸,你也有爷爷,这就是多重继承
然后object是所有类共同的父类,也就是他们的祖宗
2.5方法重写
什么叫方法重写,实际上就是当父类继承下来的方法无法满足父类的需求,子类可以用方法重写一个方法名,参数,都一样的方法去覆盖父类的方法,这就叫方法重写。
重写之后:方法的访问遵循就近原则。
也就这个样子,注意在方法重写之前,要加上@Override来表示你已经重写了这个方法
其实只要记住八个字就可以了也就是声明不变,重新实现
2.6子类访问成员变量的特点
就一个原则,就近原则 很简单的。
2.7this关键字与super关键字
3.面向对象高级
3.1多态
什么是多态
多态分为行为多态和对象多态,多态是继承,在实现下的一种情况
比如说teacher和student都是people的子类
也是说,当父类变量接受子类对象的时候,这就叫做对象多态,p1与p2都是people类型,但是p1与p2都是指的对象不同,这种现象叫做对象多态。都可以调用run方法,但是两个run方法的行为不一样,这种现象叫做,行为多态。
多态的好处
我们刚刚已经认识多态了,那我们就来看看多态的好处有那些
对于多态来说,
便于维护和扩展
就比如说在定义方法时
用父类来作为形参,那就可以接受一切子类
还有一个知识点就是类型转换
虽然多态的好处有很多,但是他也有不足,他无法使用子类中特有的方法举个例子
所以就出现了类型转换这个方法,将他转换成子类类型才可以
if(父类变量 instanf 子类类型){
子类 变量名 = (子类)父类变量;
}
这样转换了之后就可以在大括号里面使用私有方法了;
对于多态类型转换问题,原本是什么类型才能转换成什么类型。
3.2final关键字
这个很简单,final这个单词的意思就是最终的,最后的,这个修饰符,它可以修饰类,可以修饰方法,也可以修饰变量
如果他修饰类的化他就不能被继承
如果他修饰方法的化,他就不能被重写
如果他修饰变量的化他就是会变成常量,也就是只能被赋值一次
3.3抽象类
首先我们肯定会问什么是抽象类,在Java 中有一个关键字是abstract,它可以修饰类,也可以修饰方法
被abstract修饰的类叫做抽象类
被abstract修饰的方法叫做抽象方法(不允许有方法体)
构造方法也可以有
public abstract class people {
private String name;
static int age;
public people() {
}
public people(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static int getAge() {
return age;
}
public static void setAge(int age) {
people.age = age;
}
public abstract void run();
}
抽象类他是不能创造对象的,一创造就会报错
他虽然不能创造对象,但是它可以让其他子类继承他,但是要重写他里面的抽象方法
子类如果不想重写父类的抽象方法,那子类也得是抽象类
他的好处,我们来个题目看一下
这样这个题目就完成了,
1.用抽象类可以把父类中相同的代码,包括方法声明都抽取到父类,这样能更好的支持多态,一提高代码的灵活性。
2.反过来用,我们不知道系统未来具体的业务实现时,我们可以先定义抽象类,将来让子类去实现,以方便系统的扩展。
4.接口
什么叫接口,接口的语法 是什么
语法:
public interface 接口名{
成员变量(常量);
成员方法(抽象方法);
]
接下来可以让我们来实现一个接口
然后接口使用被类实现的,我们称之为实现类,(implements)
一个类可以继承多个接口,同时也被重写里面的抽象方法
然后就是接口的,好处让我们弥补了单继承的不足,我们可以用接口来实现,我们还可以实现多种业务场景的转换。
1.一个接口继承多个接口,如果多个接口中存在相同的方法声明,则此时不支持多继承
2.一个类实现多个接口,如果多个接口中存在相同的方法声明,则此时不支持多实现
3.一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会有限使用父类的方法
4.一个类实现类多个接口,多个接口中有同名的默认方法,则这个类必须重写该方法。
5.内部类
什么是内部类,其实顾名思义就是,在类的里面还有一个类,那个类就是内部类
这就是内部类,它分为成员内部类,静态内部类,局部内部类,还有匿名内部类
成员内部类
成员内部类可以看成和成员变量,成员方法一样,是类里面的一个普通成员,来个代码演示一下
他怎么创建对象呢就是
外部类.内部类 变量名 = new 外部类().new内部类()
调用方法:
变量名.方法名
静态内部类
静态内部类就是用static关键词修饰的他就只属于外部类,
静态类访问外部类的实例变量是不可以的,但是他访问外部类的静态变量是可以的。
创建对象:
//格式:外部类.内部类 变量名 = new 外部类.内部类();
Outer.Inner in = new Outer.Inner();
调用方法
in.test();
局部内部类
什么叫做局部内部类
局部内部类其实就是在方法中定义的,只在方法中可行,所以在开发中用的很少
匿名内部类
什么叫做匿名内部类,匿名内部类其实就是程序员不用给他声明名字的一个类,他的格式如下
new 父类/接口(参数值){
@Override
重写父类/接口的方法;
}
这就是匿名内部类
他的用法
就比如你想在不创建子类的情况下,创建子类对象,就可以使用内部类
他的作用其实就是简化了子类的创建,实现类的书写格式
他的应用场景就非常好理解
public interface swimming {
void swim();
}
public class test {
public static void main(String[] args) {
swimming s1 = new swimming() {
@Override
public void swim() {
System.out.println("狗爬的飞快");
}
};
go(s1);
swimming s2=new swimming() {
@Override
public void swim() {
System.out.println("小猪也不赖");
}
};
go(s2);
}
public static void go(swimming s){
System.out.println("开始");
s.swim();
System.out.println("结束");
}
}
这样就懂了吧
面向对象的面试题:
1.面向对象和面向过程的区别是什么
面向过程是问题拆成一个个方法,使用方法来执行最后解决
面向对象是吧所有属性提取出来然后封装到类中,利用对象,调用对象来解决问题
2.创建一个对象用什么标识符,对象实例和对象引用有什么不同
创建对象用的是new关键字,对象引用时储存在栈中,而对象实例时储存在new关键字在堆开辟的空间中
3.对象相等与引用相等的区别是什么
对象相等其实时对象内容的相等
引用相等时地址值的相等
4.类的构造方法有什么作用
类的构造方法是一种特殊的方法,他的作用是完成对象的初始化
5.构造方法有哪些特点,他能被重写吗
特点:
1.方法名与类名相同
2.没有返回值,也不能用viod声明
3.系统自动调用
他不能得重写,但是他能被重载,重载就是方法名相同,但是参数不同。
就想到了有参构造和无参构造
6.然后就是谈一谈你对面向对象三大特征的认识
然后我们都知道面向对象三大特征就是封装继承与多态,先来谈一下封装,封装顾名思义,他就是物品的包装袋一样,将物体包在里面,他就是把对象的属性,利用private封装在类中,可以用特殊方法调用他们也是就get/set方法,当不想被别人看是也可以不被查看,然后就是继承,看名字上就是容易想到父亲和儿子,儿子圣体里面有父亲的一部分基因,这既是儿子继承了父亲的变量和方法,私有化的除外,当父亲和儿子面对相同的事的时候,也会有不同的反应,也就是方法的重写,继承不仅大大提高了代码的运行效率,还提高了代码的复用性,节约了我们大量创建类的时间。同时需要注意的是,父类的私有化类型,子类不发访问,只能拥有。