面对对象2续 访问权限修饰符 封装,继承,多态
包
包 :包就是一个文件夹
包的作用:
避免类重名
按照不同功能管理类
控制访问权限
包(package)的命名规范
在包名中,可以使用.号来区分包的级别;包名一般情况下是小写
第一级 指该项目的类型,如com,org,gov等,
第二级 指项目所开发或者运行的公司名称,如:oracle,sun,huawei等
第三级 指项目的名称,如:bcms,oa,erp,cms等
第四级 指项目模块的名称,如:bean,action,exception等
包可以更好得管理逻辑相关的类,可以控制不同包之间的访问权限
导入外部包的类,关键字“import”
例如使用Scanner控制台输入时
package school;
import java.util.Scanner;
public class Test {
Scanner scanner=new Scanner(System.in);
}
访问权限修饰符
访问权限修饰符
public
protected
(default)
private
他们的权限从大到小依次为
public 公共权限 修饰类,属性,方法. 可以被任意类访问
protected 受保护的权限 修饰属性和方法
可以被同包的列访问,如果不是同包类,必须是该类的子类才可以访问
default 同包权限 修饰类 属性, 方法 只可以被同包的类访问
private: 私有权限 修饰属性,方法. 只能在本类中访问
面对对象语言的三大特征
封装
继承
多态
封装
封装的概念
封装:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问
封装的好处
只能通过规定方法访问
隐藏类的实现细节
方便加入控制语句
方便修改实现
具体表现
属性使用private权限
方法使用public权限
public class Demo5{
private String name;//使用private将成员变量隐藏,即封装
public String getName (){
return name;
}
public void setName(String name){//为私有的属性提供专门的方法进行访问
this.name = name;
}
}
在代码实现前,先看看this关键字
this关键字
this关键字代表自身类的对象
使用this关键字引用成员变量
使用this关键字引用成员方法
注意:this关键字必须放在非静态方法里面
封装的具体代码实现
public class Person {
private String name;//使用private将成员变量方法隐藏,即封装
private int age;
//为私有的属性提供专门的方法进行访问
public void SetName(String name){
this.name=name;//this 显示的表示当前正在访问的对象
}//this.name现在相当于a.name 因为name变量被隐藏了,通过专门的方法访问它
public String GetName(){
return name;
}
public void SetAge(int age){
this.age=age;
}
public int GetAge(){
return age;
}
}
public class PersonTest {
public static void main(String[] args) {
Person a=new Person();
a.SetName("tom");
System.out.println(a.GetName());
a.SetAge(18);
System.out.println(a.GetAge());
}
}
继承
继承是从已有的类中派生出新的类,新的类能吸收已有类的属性和行为,并能扩展新的能力。
1,在JAVA中使用extends关键字来表示继承关系。
2,JAVA不支持多继承,单继承使JAVA的继承关系很简单,一个类只能有一个直接父类。
3,继承之后子类可以调用父类的所有非私有属性和非私有方法
何时使用继承?
继承与真实世界类似,猫是动物,狗也是动物
那就可以将猫类和狗类看做是动物类的子类,将猫狗共有的属性和行为放到父类中,父类也就是动物类.
继承是代码重用的一种方式.
继承的形式
继承的形式:
[访问权限修饰符][修饰符] 子类名 extends 父类名{子类体}
public class Dog extends Animal{//Dog继承了Animal
//......
}
子类可以直接调用父类中的方法,哪怕这些方法子类没有
public class Animal {
public void eat(){
}
}
public class Dog extends Animal{
public static void main(String[] args) {
Dog dog=new Dog();
dog.eat();
}
}
上述例子中,我们得出结论
Dog类是 Animal类的子类, Animal类是Dog类的父类
Dog类是 Animal类的派生类, Animal类是Dog类的基类
继承的传递性
C类从B类继承,B类又从A类继承
那么C类就具有B类和A类的所有非私有属性和非私有方法
当一个没有继承任何一个类时,jvm会默认让类继承Object类
Object是 java为所有类提供的基类
public class Animal extends Object{
public void eat(){
}
}
public class Dog extends Animal{
public static void main(String[] args) {
Dog dog=new Dog();
dog.eat();
}
}
继承中的构造方法
子类构造方法总是先调用父类构造方法,默认情况下,调用父类无参构造方法
可以在子类构造方法的第一行,使用super关键字调用父类任意一个构造方法
如果用super,必须写在方法的第一句
如果子类的构造方法中没有显式地调用基类构造方法,则系统默认调用基类无参数的构造方法。
原因:子类创建后需要调用父类的方法,所以在创建子类对象是父类也需要同时被创建.在子类构造方法被调用输出时,父类的构造方法也会被输出.
public Animal(){
super();
System.out.println("父类的构造方法");
}
public Dog(){
super();
System.out.println("子类的构造方法");
}
在输出Dog的构造方法时,默认会将他的父类构造方法一起输出
super关键字用途
super关键字代表父类的引用,在程序中主要的用途
在子类构造方法中要调用父类的构造方法,需要注意:super语句只能出现在子类构造方法体的第一行。
用“super.成员变量名”来引用父类成员变量
用“super.方法名(参数列表)”的方式访问父类的方法。
与this的区别,this通常指代当前对象,super通常指代父类。
在子类中使用super关键字还可以给有参的父类构造方法赋值
public Animal(int m){
}
public Dog(){
super(20);//super可以给父类的有参构造方法赋值
System.out.println(n);
}
方法的重写(OverRide)
在子类中可以根据需要对从基类中继承来的方法进行重写。
方法重写规则
方法名相同、参数列表相同;
返回值类型相同;
访问权限等于或大于父类权限;
注意:构造方法不能重写
public class Animal {
public void eat(){
}
}
public class Dog extends Animal{
//@Override注解 理解为标签
//表示此方法是从父类中重写的
@Override
public void eat() {
super.eat();//super表示当前类的父类对象,super在子类中可以通过super访问父类成员
}
父类中的实现方式不能满足子类要求时,使用方法的重写
重写的要求:子类不能改变父类的结构,且子类的权限大于父类
类之间的关系-关联,依赖
关联关系
对象和对象之间的连接。在Java中,关联关系的代码表现形式为一个类做为另一个类的属性类型存在。
即“有”的关系:”has-a”
关联关系分为单向关联和双向关联
单向关联: A类关联B类。
双向关联:A类关联B类,B类关联A类;
关联关系的多重性
一对一关联一个学生,只能在一个班级里学习。
例:
~~~java
public class Classes{
private Student cla;//班级
}
public class Student{
}
~~~
一对多关联:一个学生,可以参加多个班级学习。
解决一对多的关联的方案
集合
数组
private Mobile[] mobiles;//一对多关联
依赖关系(use-a)
指一个类A使用到了另一个类B
依赖关系的特性
这种关系是具有偶然性的、临时性的、非常弱的,但是类B的变化会影响到类A。
依赖具体表现
在代码层面,依赖关系表现为类B作为参数被类A在某个method
方法中使用
例如
//依赖关系 Person中某个方法
public void feedAnimal(Dog dog){
dog.eat();
}
依赖与关联
关联是“HAS”关系,依赖是“USE”关系
A类关联B类,指的是B类对象作为A类的属性存在,称为“has”关系。
A类依赖B类,指的是B的对象作为A类的方法参数存在,称为“use”关系。
多态
同一种事物,在不同时刻表现不同的状态
多态存在的三个必要条件
要有继承(包括接口的实现)(前提条件)
要有重写(前提条件)
父类引用指向子类对象
当编译期类型是父类,运行期类型是子类时,被称为父类引用指向子类对象
class Animal{
……
}
class Cat extends Animal{
……
}
class Dog extends Animal {
……
}
Animal x = new Cat() //Animal 的引用指向Cat的对象
多态环境下对成员方法的调用
class Animal{
void show() {
System.out.println(“Anmial");
}
}
class Cat extends Animal{
void show() {
System.out.println(“cat");
}
}
Animal x = new Cat()
x.show() //调用的是子类中的方法
简单的说,成员方法多态方式调用编译看左边,运行看右边.
静态方法和成员变量以多态方式调用 运行时以左边为准,
多态环境下对成员变量的调用
class Animal{
int num = 3;
}
class Cat extends Animal {
int num = 4;
}
…….
Animal x = new Cat()
x.num; //调用的是动物类中的成员变量。
成员变量不存在被子类覆写的情况,只有成员方法实覆写
多态环境下对静态成员方法的调用
class Animal{
static void show() {
System.out.println(“Animal");
}
}
class Cat extends Animal {
static void show() {
System.out.println(“Cat");
}
}
Animal x = new Cat()
x.show() //调用的是动物类中的静态成员方法。
静态方法多态方式调用,运行时以左边为准
方法具有多态性
class Animal{
void eat() {}
}
class Cat extends Animal{
void eat() {}
}
class Dog extends Animal{
void eat(){}
}
//方法的形式参数类型是父类类型,而传递的实际参数可以是任意子类的对象
test.method(dog//这是实参);
method(Animal animal//形参){
animal .eat();
}
方法参数多态性的好处是可以提高代码的扩展性
向上转型:向上转型为父类类型
Animal dog=new Dog();//向上转型
向上转型级父类代表所有子类
缺点是只能使用父类中的方法,比如在dog类中写入方法,在多态方法中不能直接调用,只能使用父类的方法,不能使用子类方法
Test1 test1=new Test1();
test1.feedAnimal(dog);
}
/*
多态缺点:向上转型为父类类型,弊端:不能访问子类中特有方法
比如在Dog类中写入方法,在下面的多态方法中不能直接调用 只能使用父类的方法,不能使用子类的方法
*/
public void feedAnimal(Animal animal){
animal1.eat();
if(animal1 instanceof Dog){//在运行时检测判断animal中实际包含的是否是他的类型
Dog dog=(Dog) animal;//向下转型 由父类类型转换为子类类型(Dog )animal
dog.play();
}
if (animal1 instanceof Cat){
Cat cat=(Cat)animal;
cat.catplay();
}
}
如上,向下转型 由父类类型转换为子类类型(Dog )animal
为了使用子类中的特有方法,就需要使用向下转型,