封装
面对对象有3个核心:封装,继承,多态。
-
封装:主要是将类中的部分代码实现细节隐藏、封装起来,不直接对外提供访问;
-
继承:主要体现的父子类的关系上,提高了软件的可重用性和可扩展性;
-
多态:包括编译时多态和运行时多态,通过调用不同参数或名称的方法来决定父类对象动态调用哪个子类方法,增强了代码的灵活度。
封装:隐藏类的内部细节,提供公共的方法来访问内部数据
封装的好处:
- 隐藏细节,保护内部的安全
- 控制内部的细节
- 降低耦合
封装的实现
1.属性私有化
2.提供公共的get和set方法
封装成员变量
在没有权限修饰符修饰的成员变量,默认情况下可以被外界随意访问,一旦使用private私有权限修饰符修饰,成员变量就不会被外界随意访问,同时可以提供对应的getXxx
方法 、setXxx
方法来控制内部逻辑代码。
使用格式:
private 数据类型 变量名;
// 同时提供成员变量的getXxx、setXxx方法
操作演示:
1.使用 private
修饰成员变量,代码如下:
public class Student {
private String name;
private int age;
}
2.提供 getXxx
方法 / setXxx
方法(快捷键【Alt+Shift+S】),可以来控制访问成员变量的方式,代码如下:
public class Student {
// 使用private封装成员变量
private String name;
private int age;
// 提供对应的getXxx`方法 / `setXxx` 方法
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;
}
}
3.使用
public class PrivateVariableDemo {
public static void main(String[] args) {
Student stu= new Student();
// stu.name="tom"; // 编译报错,已经无法直接访问private私有变量
// 给私有变量赋值
stu.setName("杨幂");
// 获取对象私有变量的值
String name=stu.getName();
System.out.println(name);
}
}
封装方法
在没有权限修饰符修饰的成员方法,默认情况下可以被外界随意访问,一旦使用private私有权限修饰符修饰,成员方法就不能被外界。针对这种private修饰的成员方法,我们叫做私有方法,仅对本类中的其他方法使用。
使用格式:
private 静态修饰符 返回值类型 方法名(参数列表){ 方法体 };
操作演示:
1.使用 private
修饰成员方法,代码如下:
public class PrivateMethodDemo {
public static void main(String[] args) {
int[] arr= {1,2,3,4,5};
// 调用本类的私有方法
int sum= getSum(arr);
System.out.println(sum);
}
// 定义一个私有方法
private static int getSum(int[] array) {
int sum=0;
for (int i = 0; i < array.length; i++) {
sum+=array[i];
}
return sum;
}
}
封装类
private私有修饰符修饰的类只能作为内部类使用,也就是说在一个公开类的内部又声明了一个私有的类。
使用格式:
public clss 外部类名{
private class 内部类名{ 内部类成员 }
外部类成员
}
实例:
public class PrivateClassDemo {
// 定义一个私有的内部类
private class User{
// 私有的内部类方法
public void test() {
System.out.println("私有内部类测试方法");
}
}
// 外部类入口main方法
public static void main(String[] args) {
// 创建外部内对象,通过外部内对象来访问内部类对象
PrivateClassDemo p= new PrivateClassDemo();
User u=p.new User();
u.test();
}
}
为什么不能用private封装外部类?
Java封装特性的本质作用是减少代码耦合度,隐藏内部实现细节,控制内部代码的可见性。private修饰成员变量,可以考虑使用get/set方法对外提供访问入口;private修饰成员方法,可以让内部其他方法访问;private修饰内部类,可以让外部类访问。但是,如果private修饰了外部类,那就没法进行访问了,那这个封装的外部类就没有存在的意义了,因此Java不允许适用private修饰外部类,只允许使用public、default这两种级别的权限修饰符进行控制。
标准的JavaBean(实体类)
用来描述现实生活中具体事务的类就叫实体类。
JavaBean
是 Java语言编写类的一种标准规范。符合JavaBean
的类,要求类必须是具体的和公共的,并且具有无参数的构造方法,提供用来操作成员变量的set
和get
方法。
public class ClassName{
// 成员变量
// 构造方法
// 无参构造方法【必须】
// 有参构造方法【建议】
// 成员方法
// getXxx()
// setXxx()
}
编写符合JavaBean
规范的类,以学生类为例,标准代码如下:
public class Student {
//成员变量
private String name;
private int age;
//构造方法
public Student() {}
public Student(String name,int age) {
this.name = name;
this.age = age;
}
//成员方法
publicvoid setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
publicvoid setAge(int age) {
this.age = age;
}
publicint getAge() {
return age;
}
}
测试类,代码如下:
public class TestStudent {
public static void main(String[] args) {
// 无参构造使用
Student s= new Student();
s.setName("柳岩");
s.setAge(28);
System.out.println(s.getName()+"---"+s.getAge());
//带参构造使用
Student s2= new Student("赵丽颖",28);
System.out.println(s2.getName()+"---"+s2.getAge());
}
}
访问权限修饰符
概述
在Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限:
-
public:公共的。
-
protected:受保护的。
-
default:默认的(默认什么都不用写)。
-
private:私有的。
不同权限的访问范围
可见,public具有最大权限。private则是最小权限。
编写代码时,如果没有特殊的考虑,建议这样使用权限:
-
成员变量使用 private ,隐藏细节。
-
构造方法使用 public ,方便创建对象。
-
成员方法使用 public ,方便调用方法;私有方法使用private,仅对内提供访问。
继承
继承介绍
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
生活中的继承:
Java中的继承和现实生活中的继承是一样的
说明: 在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类,子类会自动拥有父类所有可继承的属性和方法。
为什么要有继承?
继承可以减少冗余的代码
使面向对象更贴近现实生活
继承的使用
子类通过extends关键字来继承父类
示例:
// 父类
public class Animal {
private String name;
public void run() {
System.out.println("动物在奔跑");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// 子类
public class Rabbit extends Animal {
// 打印一下名字
public void printName(String name) {
System.out.println("name=" + name);
}
}
// 测试类
public class ExtendsTest {
public static void main(String[] args) {
Rabbit r= new Rabbit();
// 通过父类方法为属性赋值
r.setName("小白兔");
// 调用从父类继承的方法
r.run();
// 调用本类方法
r.printName(r.getName());
}
}
继承后的特点
- 子类可以继承到父类的非私有的属性和非私有的方法
- 如果子类有相同的属性,优先使用子类的属性
- 如果子类有相同的方法,优先使用子类的方法
- 子类除了拥有继承到的属性和方法外,还可以拥有自己独有的属性和方法
方法重写
重写发生在父子关系,表示子类覆盖父类的方法
重写要求子类方法的方法名,参数列表,返回值,权限修饰符(子类权限修饰符不能比父类更严格)都与父类一致
什么时候使用方法重写
父类行为不满足子类需求时,子类可以重写父类的形为
重写与重载的区别
- 重载是发生在本类当中,重写是发生在父子关系中
- 重载要求方法名相同,参数列表不同。而重写要求方法名、参数列表、返回值相同,权限修饰符不比父类更严格。
- 重写可以使用@override修饰
- 同一方法重载可以是多个,而重写只能是一个。
面试题: 构造方法能被继承吗?能被重载吗?能被重写吗?
不能,能,不能
object
object是Java中所有类的父类,所有的类都隐式的继承了object
super关键字
super和this类似,但是super表示父类对象。
super、this用法对比:
this.成员变量 -- 本类的
super.成员变量 -- 父类的
this.成员方法名() -- 本类的
super.成员方法名() -- 父类的
this(...) -- 本类的构造方法
super(...) -- 父类的构造方法
示例:
class Fu {
int n=3;
public void run() {
System.out.println("Fun run()");
}
public Fu() {
System.out.println("Fu()");
}
}
class Zi extends Fu {
int n=5;
// 1、变量调用
public void test() {
System.out.println("Fu N="+super.n);
System.out.println("Fu N="+this.n);
}
public void run() {
System.out.println("Zi run()");
}
// 2、成员方法调用
public void runTest() {
super.run();
this.run();
}
// 3、构造方法调用
public Zi(){
// super()调用父类空参构造方法,默认已经提供,可以省略
super();
System.out.println("Zi()");
}
}
public class ExtendsDemo4 {
public static void main(String[] args) {
// 创建子类对象
Zi z = new Zi();
z.test();
z.runTest();
}
}
小提示:子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。
super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现
final关键字
Java提供有一个final关键字,中文意思是最终、终极的意思,在Java中代表不可变更的意思。final关键字可以用来修饰类、成员变量、成员方法。
-
final修饰类:表示最终类,也就是此类不能被继承;
-
final修饰变量:表示常量,也就是一个变量的值始终如一,无法变更;
-
final修饰方法:表示最终方法,也就是此方法不能被重写。
示例:
// 1、final类
public final class Hello {
。。。
}
// 2、final方法、变量
public class Hello {
private final int n=1;
public final void run() {
System.out.println("hello world");
}
}
注意:
-
被final修饰的成员变量,必须进行初始化赋值,且值不能变更,否则编译出错;
-
被final修饰的成员变量,通常会结合final和static关键字一起使用,表示一个全局的静态常量,常量名用大写;
-
被final修饰的局部变量,不能使用static修饰,同时可以不用先初始化赋值,使用时进行一次赋值即可,后续也不能变更;
-
final修饰基本数据类型,表示该基本数据类型的值一旦在初始化后便不能发生变化;
-
final修饰引用数据类型,则在对其初始化之后便不能再改变引用地址了,但该引用所指向的对象的内容是可以发生变化的。