java中面向对象的三大特征
(1)封装
所谓封装指的是隐藏对象的属性以及实现细节,仅对外提供访问方式,将不需要对外提供的内容进行隐藏,把属性隐藏对外提供访问方式
封装保证了能限制外部可以访问的内容,使得数据更安全。对于封装好的类来说,使用者只需要知道如何实现他的功能而无需了解他的内部细节,封装的具体实现使用的是权限修饰符
下面做代码演示(以字段为例)
public class Test{
String name = "张三";
}
public class TestMain{
public static void main(String[] args){
//实例化Test对象
Test test = new Test();
//获取并打印Test对象中的name
System.out.println(test.name);
//修改Test对象中的name
test.name = "李四";
//获取并打印Test中的name
System.out.println(test.name);
}
}
运行结果如下
张三
李四
可以看出一但实例化了Test对象之后可以随意操作对象中的字段数据,而如果我们不想让人随意修改其中的数据,又要够能够读取到数据就要用到封装了
public class Test{
//private修饰符将字段私有化
private String name = "张三";
//提供get方法获取私有化字段数据
public String getName(){
return name;
}
}
public class TestMain{
public static void main(String[] args){
//实例化Test对象
Test test = new Test();
//获取并打印Test对象中的name
System.out.println(test.name);
//修改Test对象中的name
test.name = "李四";
//获取并打印Test中的name
System.out.println(test.name);
}
}
结果如下
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The field Test.name is not visible
The field Test.name is not visible
The field Test.name is not visible
将TestMain类改成如下
public class TestMain{
public static void main(String[] args){
//实例化Test对象
Test test = new Test();
//获取并打印Test对象中的name
System.out.println(test.getName());
}
}
结果如下
张三
可以看出对字段加上了private权限修饰符后,即便实例化Test类的对象后,还是不能访问对象中的字段,这时只有其内部能够访问私有化的字段,同理可以提供set方法修改字段
下面演示一种常用的封装方式
public class Test{
//private修饰符将字段私有化
private String name = "张三";
//提供get方法获取私有化字段数据
public String getName(){
return name;
}
//提供set方法设置私有化字段是数据
public void setName(String name){
this.name = name;
}
//提供无参构造方法
Test(){
}
}
封装的优点
1、良好的封装能够减少耦合。
2、类内部的结构可以自由修改。
3、可以对成员进行更精确的控制。
4、隐藏信息,实现细节。
(2)继承
使子类对象的实例具有父类的非私有的字段和方法
在编写java程序的过程使用extends关键字建立继承关系,一个子类只能拥有一个直接父类,而一个父类可以同时拥有多个子类。
代码示例如下:
class Animal{
//私有化的字段不会被子类继承
private int age;
//非私有化的字段可以被子类继承
String name = "Animal";
//私有的方法不会被子类继承
private void drink(){
System.out.println("Animal drink");
}
//非私有的方法可以被子类继承
public void eat(){
System.out.println("Animal eat");
}
}
//继承Animal的一个Person类
class Person extends Animal{
}
//继承Animal的另一个子类
class Cat extends Animal{
}
虽然Person和Cat中什么都没有写,但是他们继承了Animal中的非私有字段和方法(以Cat为例)
public class Test{
public static void main(String[] args){
//实例化Cat对象
Cat cat = new Cat();
//打印输出Cat继承到的Animal中的name属性
System.out.println(cat.name);
//调用Cat继承到的Animal中的eat方法
cat.eat();
}
}
得到结果
Animal
Animal eat
子类还可以对父类的中原有的方法或者字段进行覆写以修改或者实现新的功能
下面以Cat类为例
class Cat extends Animal{
//覆写了Animal中的字段
String name = "Cat";
//覆写了Animal中的方法
@Override
public void eat(){
Sysrem.out.println("Cat eat");
}
}
public class Test{
public static void main(String[] args){
//实例化Cat对象
Cat cat = new Cat();
//打印输出Cat中已经覆写的name属性
System.out.println(cat.name);
//调用Cat中已经覆写的eat方法
cat.eat();
}
}
得到结果
Cat
Cat eat
虽然子类没有继承父类的构造方法,但是可以使用super关键字调用父类的构造方法
(3)多态
子类具有父类的属性
子类可以直接使用父类的类型
在调用使用父类类型的方法时,首先会在父类中查找, 如果没有不能完成此次调用
如果能在父类中查找到,而子类中没有覆写则使用子类继承到的父类方法
如果能在父类中查找到,而子类中覆写的该方法则使用子类覆写的方法
在调用使用父类类型的字段是时,首先会在父类中查找, 如果没有不能完成此次调用
如果能在父类中查找到,则直接使用父类的字段
代码演示如下:
class Animal{
//非私有化的字段可以被子类继承
String name = "Animal";
//非私有的方法可以被子类继承
public void eat(){
System.out.println("Animal eat");
}
}
//继承Animal的一个Person类
class Person extends Animal{
//子类中覆写的字段
String name = "Person";
//覆写父类中的eat方法
@Override
public void eat(){
System.out.println("Person eat food");
}
}
//继承Animal的另一个子类
class Cat extends Animal{
}
有一个字段和一个方法的父类Animal中,分别有定义了同名新字段的子类Person和空白的Cat子类
public class Test{
public static void main(String[] args){
//实例化Person对象
Animal person = new Person();
//实例化Cat对象
Animal cat = new Cat();
//调用Person子类中的字段
System.out.println(person.name);
//调用Person子类中已经覆写的eat方法
person.eat();
//调用Cat子类继承到的字段
System.out.println(cat.name);
//调用Cat子类继承到的方法
cat.eat();
}
}
运行结果为
Animal
Person eat food
Animal
Animal eat