面向对象的三大特征:封装,继承,多态。
类的封装(有不懂回顾老师的笔记文件chap3)
1.为什么要对类进行封装:
原因:将类的相关属性进行隐藏,不对外开放。避免一些安全性问题。
2.封装最常见的例子:就是针对实体类。
3.需要掌握如何正确编写实体类。
4.今日知识点总结:如果可以从0到1 正确编写一个实体类,且知道每行代码的意义,就表示今天的知识点掌握透了。
习题:(具体写法查找老师发的文件chap3)
有一个Person实体类、拥有Id name age 三个属性。
将其声明成一个实体类
public class Person {
private int id;
private String name;
private int age;
空参和有参构造方法
public Person() {//空参构造方法 有了它。在别处才可以通过Person p = new Person(); 来实例化
}
有参构造方法
反问:上面明明写了无参的为什么还要写有参的。可不可以不写
//当然可以不写 ,但是如果只有无参的,那么实例化之后需要一一赋值。比较麻烦
//如果有 有参 实例化的同时 即可完成赋值操作
//例如 Person p = new Person(123, "张三" , 18);
public Person(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
}
例如:学生实体类为例:
拥有id name sex 三个属性。
步骤1:创建该类
步骤2:声明属性 需要通过private修饰
步骤3:由于属性都被私有化了。所以外部无法通过属性来进行操作。所以需要对外开放若干个方法,对属性进行操作。
步骤4:对属性进行set/get方法的创建 可以通过快捷键的方式
步骤5:需要生成一个toString方法,原因:随时检查实体类的属性值是否正确 如果没有加,打印对象将会得到内存地址
加了toString,打印对象将会得到对象的属性值。
步骤6:创建对应的构造方法
构造方法的概念:
1.构造方法是一个特殊的方法。无法被显示调用,只能在被实例化的时候自动调用。
2.意义:实例化(没有构造方法就无法实例化)。
3.每个类都至少含有一个构造方法,如果没有声明就说明存在一个默认的无参构造方法
类名 变量名 = new 类名();//这里没有参数
4.一般来说:一个类至少有2个构造方法,1个无参构造方法 1个有参构造方法。
this表示的意思
public void setId(int id) {
this.id = id;//加了this表示当前类下的属性,没有加this就是方法的参数列表的属性
}
生成实体类的快捷方式
由于实体类的规范。所有很多开发工具都有自动生成实体类的快捷键、
只需要声明属性即可。
1.通过快捷键生成该实体类的set.get.toString方法即可。
a.将鼠标焦点放在代码想生成的位置
b.鼠标右键 看操作(需要靠自己记住的选项)
如何创建一个实体类
如何创建一个实体类:(不会找老师笔记文件Test-Demo3)
1.私有化声明属性
2.提供属性的set.get方法
3.提供有参和无参构造方法
4.提供toString方法 把实体类的打印:从地址改成能够看清的值
Java的四大修饰符:
public :任何地方都可以访问
protected:受保护,只有在同一个包下,或者不同包,但是具有继承关系可以访问
default(不写) :默认的:只有在同一个包下,可以访问
private :私有的,只有当前类可以访问
final修饰符
final表示最终的。用来修饰类,或方法,或属性,或对象。
语法如下:
修饰类: public final class Xxx{ }
修饰方法:public final 返回类型 方法名(参数列表){}
修饰属性:final 数据类型 变量名 = 属性值;
修饰对象:本质就是修饰一个变量名
如果final修饰一个类,就表示该类是最终类。它无法被继承。
如果final修饰一个方法,就表示该方法无法被子类重写
如果final修饰一个属性,就表示该属性是一个最终属性,无法修改值。
如果final修饰一个对象,该对象无法重新修改,但是内部属性可以修改。
public static void main(String[] args) {
final Demo2 d = new Demo2();
d.age = 11;
d.age = 22;
System.out.println(d);
}
public void a() {
}
static修饰符
static表示静态的。
用来修饰方法或属性,可以不必通过实例化之后,再去调用相关的方法或属性。
如果是在当前类下调用,直接通过方法名或属性名调用即可。
如果是在不同类下调用,直接通过类名.方法名 或类名.属性名
语法如下:
修饰方法:
权限修饰符 static 返回类型 方法名(参数列表) { 代码体; }
修饰属性:
权限修饰符 static 数据类型 变量名 ;
适用场景:适用于公用的方法或属性。
被static修饰的:
随着类的加载而加载,且只会加载一次。
被static修饰的变量或方法要优先级高于非static修饰的变量或方法。
所以:static方法中无法调用非static方法或变量
但是非static方法可以调用static方法或变量。
通过static修饰的变量或方法,就不推荐通过实例化的形式来调用,因为随着类的加载而加载,多此一举了。
*/
static int age = 18;
public static void a1() {
}
public void a2() {
a1();
}
public static void main(String[] args) {
Demo1 d = new Demo1();
d.a1();
}
类的继承(有不懂回顾老师的笔记文件chap4)
集成概念如下:
如果不同的类之间拥有相同的属性或方法,
那么可以将这些方法或属性单独抽取出来组成一个父类,
让别的类去继承它,别的类就可以少写很多方法和属性。
这就是面向对象三大特征之一的继承。
Java中的继承和现实生活的继承非常类似。
子承父业。 父不能承子业。
子类拥有父类的方法属性,但是父类没有子类的方法或属性。
比如:
创建一个Student类,拥有studentNum,name,age,sex 4个属性。
还拥有:可以打印“我可以说话”的方法,可以打印“我可以吃饭”的方法,
可以打印“我可以上课”的方法
创建一个Teacher类,拥有teacherNum,name,age,sex 4个属性。
还拥有:可以打印“我可以说话”的方法,可以打印“我可以吃饭”的方法,
可以打印“我可以教书”的方法
分析:上述写法有何不妥。
总结:老师类和学生类中 含有相同的属性或方法。
我们推荐将其放在另外一个Person类中
然后让Teacher类和Student继承Person类即可
怎么继承一个类
语法如下:
class A extends B{
}
我们称A为子类,B为父类。
额外补充:
Java是单继承的语言。每个类最多只能显式继承一个类。
但是每个类可以被多个类同时继承。
每个类都隐式继承Object类,Object是任何类的父类。
子父类中成员变量的特点:
假如存在特殊情况:
子类和父类都拥有相同的成员变量属性、
通过实例化 调用子类的属性 到底是用的子类的还是父类的。
答案:实例化的谁,就用的谁。
假如说想在子类的内部方法共有属性,应该怎么写?
如果直接通过属性名,就默认表示子类。
也可以通过this.属性名 来表示子类
如果想使用父类的共有属性 加上super关键字即可 例如super.money
子父类中成员方法的特点:
子承父类:如果子类没有才继承父类的相关属性或方法。
特殊情况:如果子父类拥有公共的方法,到底调用的谁的?
答案:和成员变量一致。
子父类中构造方法的特点:
1.利用开发工具自动生成的构造方法,内部的第一行都有一行super();注意:只能放在第一行
2.super();表示父类的无参构造方法
3.super();如果每写就默认存在,如果写了就只会以写了的为主。
A a = new A();//实例化会自动调用对应的构造方法
实体类的编写步骤:
1.私有化定义变量属性
2.提供属性的set/get方法
3.提供toString方法
4.提供无参和有参构造方法
比如:
public A(int id) {
this.id = id;
System.out.println("我是子类的有参构造方法");
}
public A() {
super("name ");
System.out.println("我是子类的无参构造方法");
}
父类的构造方法比如:
class Father{
private String name;
public Father(String name) {
super();
System.out.println("我是父类的有参构造方法");
this.name = name;
}
public Father() {
super();
System.out.println("我是父类的无参构造方法");
}
面向对象的特征:多态
多态是继封装,继承之后的面向对象的第三个特征。
简单来说:多态指的就是:对象的多种形态,一个对象在不同条件下所变现的不同形式。
例如打印机:在黑白打印机情况下打出来为黑白,在彩色打印机情况下打印出来为彩色
多态需要依赖于继承或接口实现才能体现多态。
语法如下:
父类或接口 变量名 = new 子类或实现类( );
练习:(不会具体看老师笔记文件chap6)
创建一个父类Person,内部提供一个方法work,打印正在工作。
内部提供一个成员变量name,值为人类。
创建一个子类Teacher,内部提供一个方法work,打印正在授课。
内部提供一个成员变量name,值为老师。
利用多态的特性测试相关代码。
public class Test1 {
public static void main(String[] args) {
// Teacher t = new Teacher();
// Person p = new Person();
// System.out.println(t.name);
// t.work();
// System.out.println(p.name);
// p.work();
//以上写法才是正常的写法。
//以下写法是多态的写法:
Person p = new Teacher();
p.work();
总结1:成员变量都看=的左边。
总结2:成员方法编译看左边,运行看右边。
运行看右边指的就是:调用的是右边的方法。
编译看左边指的就是:只能看到左边的对象的方法
类的封装:关于属性的隐藏
什么是封装:顾名思义:将类的相关属性进行隐藏。只提供相关的方法,来对这些属性进行操作。
为什么明明对属性进行了隐藏,还要提供方法进行操作?
答:例如age这个属性。是一个变量,既然是变量,说明age是可以经常改变的。
既然需要改变:要么通过属性改变,要么通过方法改变。
封装的理念:希望通过方法来改变而非属性。
通过方法改变属性
为什么通过方法来改变而非属性?
原因如下:看代码 如该类所示:如果仅仅是通
A a = new A();
a.age = 222222;过属性来修改。
那么容易出现:不合理的数据可以随意修改。
class A{
int age = 18;
}
解决办法1: 如下代码所示: 进行属性的校验。缺点:没有将代码的校验封装到一个方法。
导致如果有很多属性需要校验,那么导致大量的代码出现在main方法内部,不适合阅读代码。
解决方法2: 推荐使用:将类的相关属性进行隐藏。只提供相关的方法,来对这些属性进行操作。
详情见demo2
public class Demo {
public static void main(String[] args) {
//以下写法的缺点: 代码没有进行封装。 如果有很多个属性都需要修改,那么每个属性都需要大量的代码进行校验。
A a = new A();
a.age = 50;
if(a.age>100) {
System.out.println("该数据不合理");
a.age = 18;
}else {
System.out.println("该数据合理,修改成功。");
}
System.out.println("age=" + a.age);
System.out.println(a.age);
}
}
class A{
int age = 18;
}
public static void main(String[] args) {
// 接Demo1:解决方法2: 推荐使用:将类的相关属性进行隐藏。只提供相关的方法,来对这些属性进行操作。
// 详情见demo2
//何为属性的隐藏: 通过Private修饰即可。
通过权限修饰符:用来修饰类或方法或属性等
按照权限大小排序:
public :公共的 , 任何地方可以访问
protected :受保护的,仅仅在同一个包或具有继承关系下。
default(默认,缺省) :什么都不写 例如 int age = 18;
private :私有的,只在当前类下有效
*/
//由于age已经被私有化了。所以只能提供方法来对其进行操作。
//对属性修改无法就是 set/get方法: set表示赋值(修改) get取值
B b = new B();
b.setAge(22);
System.out.println(b.getAge());
class B{
private int age;
public int getAge() {
return age;
}
public void setAge(int age123) {
if(age123>100) {
System.out.println("该数据不合理");
}else {
System.out.println("该数据合理,修改成功。");
age = age123;
}
}
}
封装最常用的地方:就是在实体类。例如学生 老师 学校 桌子
实体类一般都放在:
实体包下 com.yyzy.entity com.yyzy.pojo com.yyzy.po
代码块的类别和优先级
//例如后续需要学习链接数据库的技术,这些代码就只需要执行一次
}
/*
代码块:分为三大类分别是:
A.局部代码块:例如常见的类,方法都是通过{...} ,打大括号内部的就是局部代码块。
B.构造代码块,一般放在类的内部,用{...}包起来。优先级高于构造方法
C.静态代码块,一般放在类的内部,用static {...}包起来,优先级最高
抽象类
抽象类的概念:(具体不会看老师笔记chap5)
在编写一个类时候,往往会给它定义一些属性或方法,但是有的时候,某些方法只知道应该
存在,但是不知道它如何实现,那么该类就是抽象类,这些不知道具体如何实现的方法就叫做抽象方法。
抽象类的抽象方法都是等待子类去继承然后子类去重写父类的抽象方法。
抽象的关键字: abstract
定义抽象类: public abstract class { }
定义抽象方法: public abtract 返回类型 方法名(参数列表);
1.抽象类中可以没有抽象方法,可以有具体的方法。
2.抽象方法只能存在于抽象类中。
3.如果某子类继承了一个抽象类,那么该子类必需要重写父类的抽象方法。
//Demo1就是一个普通的类
public class Demo1 {
int age = 18;
public void method1() {
System.out.println("这是普通的方法");
}
}
package com.yyzy.test;
//此时:这个类就是抽象类 : 抽象方法
public abstract class Demo2 {
//抽象方法
public abstract void method2() ;
}
package com.yyzy.test;
//这是一个父类
public abstract class Teacher {
//这个是抽象方法
public abstract void work();
public void a() {
System.out.println(111);
}
}
接口_老师笔记chap5
接口的相关概念:
如果存在某个抽象类中全是抽象方法,而没有具体的方法,那么就可以将该抽象类彻底改成接口。
接口:只有抽象方法的一个特殊的类。
语法如下:public interface 接口名{ 抽象方法... }
由于接口中只能存在抽象方法,那么在书写接口中的方法如下:
返回类型 方法名(参数列表); //可以省略public abstract 默认就是这两个。
/*
创建一个Teacher抽象类,内部含有一个抽象方法work。
(原因:每个老师都上不同的课,所以该方法没有具有的代码,而是等子类去重写)
然后创建一个MathTeacher类,EnglishTeacher子类,去继承该Teacher类。
然后重写抽象方法。
*/
public static void main(String[] args) {
EnglishTeacher et = new EnglishTeacher();
et.work();
MathTeacher mt = new MathTeacher();
mt.work();
}
/*
创建一个接口名为Usb的接口,内部有一个方法名叫work。
创建一个类名为Phone的类和Computer的类,去实现该Usb接口,
然后重写该接口内的方法。
这是接口
package com.yyzy.test;
public interface Usb {
void work();
}
接口和抽象类的区别:
关键字:接口是interface 抽象类是:abstract
接口是等待实现类去实现。 抽象类是等待子类去继承
接口不是一个类。 抽象类是一个类。
抽象类里面可以存在普通方法。
接口里面不能存在普通方法。
*/
//抽象类:需要子类去继承 然后重写
//接口: 需要一个实现类去实现(implements)该接口。然后重写接口的相关方法。
//注意不是继承关系了 但是可以理解成继承关系。
//继承:extends 实现:implements
//此时这个Z2就是一个接口,而非一个类或抽象类
//接口里面只能存在抽象方法,所以直接将public abstract省略
public interface Z2 {
// public abstract 返回类型 方法名(参数列表);
void a1();//一般来说为了简化代码,都是直接这样写即可
public abstract void a2();
abstract void a3();
public void a4();
//以上4个方法 其实都是
//专业术语: Z3 不是Z2的子类,因为两者之间没有extends关键字。
// Z3叫做Z2的实现类。 Z2是Z3的接口
public class Z3 implements Z2 {
@Override
public void a1() {
// TODO Auto-generated method stub
}
@Override
public void a2() {
// TODO Auto-generated method stub
}
@Override
public void a3() {
// TODO Auto-generated method stub
}
@Override
public void a4() {
// TODO Auto-generated method stub
}
}