根据网上其他地方的解释,以及查找资料,将自己对java三大特性的理解展示如下。
封装:(属性私有,set/get,在set中限定一些不安全的情况)
封装是指把一个对象的状态信息(也就是属性)隐藏在对象内部,不允许外部对象直接访问对象的内部信息。但是可以提供一些可以被外界访问的方法来操作属性。
代码举例:
public class Person {
//Person类的成员变量
String name; //姓名
int age; //年龄
int sex; //性别
String role; //角色
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;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
测试:
public class ApplicationTest {
public static void main(String[] args) {
Person person = new Person(); //实例化 Person
person.setName("宇晨"); //name赋值为:宇晨
person.setAge(20);
person.setSex("男");
person.setRole("学生");
System.out.println(person.getName()+","+person.getAge()+
","+person.getSex()+","+person.getRole());
}
}
输出:
使用封装的好处
1、良好的封装能够减少耦合
2、类中的内部结构(属性)可以按照需求进行修改(重新赋值)。
3、可以对成员进行更精确的控制。
4、能够隐藏代码实现的细节。
5、系统可维护性增加了。
继承:
不同类型的对象,相互之间可能会拥有一些相同共同点。例如:教师角色应该做什么?学生角色应该做什么?家庭角色应该做什么?都有共同点就是-应该做什么。
继承的本质是对某一批类的抽象, 是使用已存在的类的定义作为基类建立新类的技术,新类的定义可以继承父类,从而增加新的数据或新的功能,但不能选择性地继承父类。通过使用继承,可以快速地创建新的类,可以提高代码的重用,程序的可维护性,节省大量创建新类的时间 ,提高我们的开发效率。
关于继承如下 3 点应该记住:
-
子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有。
-
子类仍拥有自己属性和方法,即子类可以对父类进行扩展。
-
子类可以使用自己的方式实现父类的方法。
代码举例(先介绍原始):
//定义一个Person类
/*public class Person {
//Person类的成员变量
String name; //姓名
int age; //年龄
int sex; //性别
String role; //角色
//Person类的方法
public void TeacherDoing(){ //教师要做的事情
System.out.println("老师负责传道受业!");
}
public void StudentDoing(){ //学生要做的事情
System.out.println("学生要努力学习!");
}
public void FamilyDoing(){ //家庭要做的事情
System.out.println("成为孩子最坚实的后盾!");
}
}
测试:
public class ApplicationTest {
/* public static void main(String[] args) {
Person person1 = new Person();
person1.StudentDoing();
}
}
输出:
原始方式,可以使用if判断的方式将不同角色的人的方法,放到一个方法Doing()内,根据传入的角色不同调用不同的方法。进行修改:
public class Person {
//Person类的成员变量
String name; //姓名
int age; //年龄
int sex; //性别
String role; //角色
//使用 if 判断方式选择 不同方法
public void Doing(String role) { // 集合到同一个方法内
if ("teacher".equals(role)) { //当传入角色为 teacher时
System.out.println("老师负责传道受业!");
}
if ("student".equals(role)) { //当传入角色为 student时
System.out.println("学生要努力学习!");
}
if ("family".equals(role)) { //当传入角色为 family时
System.out.println("成为孩子最坚实的后盾!");
}
}
}
测试:
public class ApplicationTest {
// 测试方式一:
public static void main(String[] args) {
Person person1 = new Person();
person1.Doing("student");
}
输出:
弊端:仅适合角色不多的情况。如果角色较多,社会产生许多If 判断代码,代码产生冗余。
方式二(继承),由于Teacher、Student、Family都有一个共同点 Doing做什么,接下来可以使用继承的方式实现代码复用。
代码举例(使用继承):
public class Person {
//Person类的成员变量
String name; //姓名
int age; //年龄
String sex; //性别
String role; //角色
//共同的方法Doing(),表示应该做的事情;
public void Doing(){ }
}
测试:
public class ApplicationTest {
// 测试方式二(使用了继承,实现多态方式):
public static void main(String[] args) {
Person person2_1 = new Teacher(); //向上转型,Person为父类,Teacher是子类
person2_1.Doing();
Person person2_2 = new Student(); //向上转型,Person为父类,Student是子类
person2_2.Doing();
Person person2_3 = new Family();//向上转型,Person为父类,Family是子类
person2_3.Doing();
}
}
输出:
多态(重要):
多态,顾名思义,表示一个对象具有多种状态,具体表现为父类的引用指向子类的实例。
多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单可以理解为:不同的对象调用统一个方法实现不同功能。(如上面继承,既是多态的摆弄先形式)。
实现多态的条件:
1、继承:对象类型和引用类型之间具有继承(类)/实现(接口)的关系 。简单理解:必须有子类和父类的继承关系;
2、重写: 子类必须按照需要重写父类的某些方法,调用的时候调用的是子类重写的方法而不是原本父类中的方法。
3、向上转型:父类引用需要指向子类对象
代码举例:
public class Person {
//Person类的成员变量
String name = "宇晨"; //姓名
public void doing(){
System.out.println("我是小-doing方法!");
}
public void Doing(){
System.out.println("我是大-Doing方法!");
doing();
}
}
继承代码:
public class Polymorphic extends Person{
String name="四夕-宇晨";
@Override
public void doing() { //重写
System.out.println("重写了小-doing()方法!");
}
public void Doing(String name) { //重载
System.out.println("我是重载方法!");
doing();
}
public void other(){
System.out.println("我是其他方法!");
}
}
测试:
public class ApplicationTest {
//测试多态:
public static void main(String[] args) {
Person person = new Polymorphic(); //向上转型,Person的引用指向Polymorphic对象。
person.Doing();
person.doing();
// person.other(); //不能调用此方法因为Person类里面,没有定义other()这个方法。
//直接调用成员变量,查看结果
System.out.println(person.name);
}
}
结果分析:
子类 Ployamorphic重载了Doing()方法,重写了doing()方法,当我们调用person.Doing()方法时,因为向上转型的原则,先会调用父类中的Doing()方法(子类中的doing()重载后丢失),在调用子类中的doing()方法。因为重写了doing()方法,当我们调用person.doing()方法时,直接调用子类中的doing()方法。
直接调用成员变量结果是:宇晨。
我们发现如果方法被重写了,他是成员变量也重复定义了,父类的引用指向子类的对象,调用的方法将是子类的,而成员变量的值将是父类的。这是java的编译机制造成的。方法时在运行的时候取值不定, 所以方法时动态绑定的,而成员变量的初值是编译的时候就绑定的。所以为了避免这类问题,java程序员通常会使用方法,而不是直接使用成员变量。
Person person = new Polymorphic(); //向上转型不需要强转
Polymorphic ploymorphic = (Polymorphic) new Person();//向下转型需要强转
ploymorphic.other(); //此时可以调用other()方法
总结:“编译看左边,运行看右边” 也就是编译的时候,会看左边引用类型是否能正确编译通过,运行的时候是调用右边的对象的方法。