面向对象和面向过程的思想对比
类是对现实生活中一类具有 共同属性 和 行为 的事物的抽象
“类”是对事物,也就是对象的一种描述,可以将类理解为一张设计图,根据设计图,可以创建出具体存在的事物
类的组成
类是对对象的描述 对象是类的实体 一个类可以创建出多个对象
类的定义
类的组成:属性和行为
类的定义步骤
public class 类名{
// 成员变量
变量1的数据类型 变量1;
String name; // 未赋值默认null
变量2的数据类型 变量2;
int age; // 未赋值默认0
......
// 成员方法 方法1
public void study(){
System.out.println("学习");
}
方法2;
......
}
对象的创建和使用
类名 对象名 = new 类名();
对象名.变量名
使用成员方法:对象名.方法名();
案例:定义一个类,然后定义一个手机测试类,在手机测试类中通过对象完成成员变量和成员方法的使用
public class Phone{
// 成员变量:品牌、价格、....
String brand;
int price;
// 成员方法:打电话、发短信、....
public void call(String name){
System.out.println("给" + name + "打电话");
}
public void sendMessage(){
System.out.println("群发短信");
}
}
单个对象内存图
两个对象内存图
两个引用指向同一对象内存图
垃圾回收
当堆内存中,对象 或 数组产生的地址,通过任何方式都不能被找到后,就会被判定为内存中的“垃圾”
垃圾会被Java垃圾回收器,在空闲的时候自动进行清理
成员变量和局部变量
private关键字:权限修饰符,可以用来修饰成员,来提高数据的安全性
get变量名();
方法,用于获取成员变量的值,方法用public
修饰set变量名();
方法,用于设置成员变量的值,方法用public
修饰// 新建Student类
public class Student{
private String name;
private int age;
public void setName(String n){
name = n;
}
public String getName(){
return name;
}
public void setAge(int a){
age = a;
}
public int getAge(){
return age;
}
public void show(){
System.out.println(name + age);
}
}
this关键字:可以调用本类的成员(变量,方法),解决局部变量和成员变量重名问题
this
代表所在类的对象引用,方法被哪个对象调用,this就代表哪个对象public class Student{
private int age;
public void method(int age){
this.age = age; // 添加this关键字,使前一个age成为成员变量,再将局部变量age赋值过去
}
}
this内存原理
封装
常见体现:
好处
构建、创造对象的时候,所调用的方法
格式
public class Student{
public Student(){
System.out.println("这是Student类的构造方法");
}
}
执行时机
作用:用于给对象的数据(属性)进行 初始化
class Student{
private int age;
public Student(int age){
this.age = age;
}
}
注意事项
标准类的代码编写和使用
/*
JavaBean类:封装数据的类
*/
public class Student{
// 私有变量
private String name;
private int age;
// 无参数构造方法
public Student(){}
//有参数构造方法
public Student(String name, int age){
this.name = name;
this.age = age;
}
//set/get方法
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public String getAge(){
return age;
}
}
分类思想:分工协作,专人干专事
分包思想:如果将所有的类文件都放在同一个包下,不利于管理和后期维护
对于不同功能的类文件,可以放在不同的包(本质上就是文件夹)下进行管理
创建包(单级包、多级包)
包的定义
package
关键字定义包package 包名;
(如果是多级包,中间用”.”进行分割)包的注意事项
类与类之间的访问
注意事项
import、package、class三个关键字的摆放位置存在顺序关系
static关键字是静态的意思,修饰符,可以修饰成员变量、成员方法
特点
注意
让 类与类之间产生关系(子父类关系),子类可以直接使用父类中非私有的成员
public class 子类名 extends 父类名{}
public class Zi extends Fu{}
优点
弊端
继承关系,导致子类 必须 拥有父类非私有属性和方法,让子类自由的世界中多了些约束
应用场景
Java继承的特点
访问顺序
如果子父类中,出现了重名的成员变量,通过 就近原则 ,会优先使用子类的 如果一定要使用父类的,可以通过
super
关键字进行区分
super关键字
super
和this
关键字的用法相似在继承体系中,子类出现了和父类中一模一样的方法声明,可以在子类中对父类方法进行重写
应用场景
当子类需要父类的功能,而功能主体子类有自己特有内容,可以重写父类中的方法,这样,既沿袭了父类的功能,又定义了子类特有的内容
区别
方法重写是子类对父类方法的增强,方法重载是针对同一个方法名的不同参数做扩展
注意事项
修饰符 | 同一个类中 | 同一个包中子类无关类 | 不同包的子类 | 不同包的无关类 |
---|---|---|---|---|
private | √ | |||
默认 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
子类中所有的构造方法默认都会访问父类中无参的构造方法
子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据(子类在初始化前,一定要先完成父类的初始化)
super();
访问特点
注意:
this()
和super()
调用构造方法时,必须放在构造方法的第一行有效语句,并且二者不能共存
使用abstract修饰并且没有方法体的方法叫做抽象方法。包含抽象方法的类一定是抽象类
定义格式
public abstract 返回值类型 方法名(参数列表);
public abstract class 类名{}
常量的命名规范
在Java中,使用
{}
括起来的代码都被称为代码块
分类
局部代码块
构造代码块
静态代码块
static
关键字修饰,随着类的加载而加载,并且只执行一次当一个类中所有方法都是抽象方法的时候,我们就可以将其定义为接口 接口也是一种引用数据类型,它比抽象类还要抽象
意义
定义和特点
public interface 接口名{}
implements
关键字表示public class 类名 implements 接口名{}
public class 类名 implements 接口名1,接口名2{}
接口的子类(实现类)
成员的特点
public
、static
、final
接口中不存在构造方法
只能是抽象方法(JDK7以前),系统会默认加入两个关键字:public
、abstract
JDK8中接口成员的特点 允许接口中定义非抽象方法,但是需要使用关键字
default
修饰,这些方法就是默认方法 定义格式:public default 返回值类型 方法名(参数列表){}
默认方法不是抽象方法,所以不强制重写,但是可以被重写,重写的时候去掉default关键字 public可以省略,但是default不能省略 如果实现了多个接口,多个接口中存在相同的方法声明,子类就必须对该方法进行重写
使用思路
类和接口的关系
同一个对象,在不同时刻表现出来的不同形态
前提
成员访问特点
优劣点
如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现 ClassCastException 异常
instanceof关键字
变量名 instanceof 类型
就是在一个类中定义一个类。举例:在A类的内部定义一个B类,B类就被称为内部类
外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象()
内部类的访问特点
也属于成员,可以被一些修饰符修饰
private
私有成员内部类访问:在自己所在的外部类中创建对象访问static
静态成员内部类访问格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
静态成员内部类中的静态方法:外部类名.内部类名.方法名();
本质上是一个特殊的局部内部类(定义在方法内部)【使用次数远远大于成员内部类和局部内部类】
new 类名或者接口名(){ 重写方法; }
Lambda表达式,是对匿名内部类进行了优化,代码更少,关注点更加明确
函数式编程思想
在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿数据做操作”
面向对象思想强调“必须通过对象的形式来做事情”
函数式思想则尽量忽略面向对象的复杂语法:“强调做什么,而不是以什么形式去做”
Lambda表达式就是函数式思想的体现
标准格式
(形式参数) -> {代码块}
->
:由英文中画线和大于符号组成,固定写法,代表指向动作使用前提
练习
ShowHandler
)ShowHandlerDemo
)中存在一个方法(useShowHandler
)方法的参数是ShowHandler
类型的在方法内部调用了ShowHandler
的show方法public class TestLambda{
public static void main(String[] args){
// 匿名内部类实现
useShowHandler(new ShowHandler(){
@Override
public void show(){
System.out.println("我是匿名内部类中的show方法");
}
});
// Lambda实现
useShowHandler(() -> {System.out.println("我是匿名内部类中的show方法");});
}
public static void useShowHandler(ShowHandler showHandler){
showHandler.show();
}
}
interface ShowHandler{
void show();
}
StringHandler
)printMessage
),该方法是有参数无返回值StringHandlerDemo
)中存在一个方法(useStringHandler
),方法的参数是StringHandler
类型的,在方法内部调用了StringHandler
的printMessage
方法public class StringHandlerDemo{
public static void main(String[] args){
// 匿名内部类实现
useStringHandler(new StringHandler(){
@Override
public void printMessage(String msg){
System.out.println("我是匿名内部类." + msg);
}
});
// Lambda实现
useStringHandler((String msg) -> {System.out.println("我是Lambda" + msg);});
}
public static void useStringHandler(StringHandler stringHandler){
stringHandler.printMessage("坚持学习!");
}
}
interface StringHandler{
void printMessage(String msg);
}
省略规则
useStringHandler(msg -> System.out.println("我是Lambda" + msg));
Lambda表达式和匿名内部类的区别
所需类型不同
使用限制不同
实现原理不同