封装:通常理解为将某个功能封装成了一个方法,例如,写一个工具类,定义了好几个常用的方法。
面向对象中的封装:是隐藏,通过(访问权限修饰符 private protected default public )选择将类中的某些信息对外开放
注意:private String name;//属性私有化, 只是封装的一种体现。
封装什么?
为了不让外部直接访问,隐藏内部具体属性、方法。
访问权限修饰符 private protected default public 修饰属性、方法
①如何访问private 修饰的属性?
setXXX() getXXX() set控制输出的条件 ,get返回值 XXX是属性
package com.feifan.javaoop.Day3;
public class Private {
//如何访问封装的属性
private String name;
//setXXX 为访问私有属性 提供方法
public void setName(String name) {
this.name = name;
}
// 返回
public String getName(){
return this.name;
}
}
package com.feifan.javaoop.Day3;
public class PrivateTest {
public static void main(String[] args) {
Private p = new Private();
p.setName("sssssss"); //输出 sssssss
System.out.println(p.getName());
}
}
那如何实现输出控制呢?
setXXX方法中加入条件语句 。 XXX表示私有属性
//setXXX 为访问私有属性 提供方法
public void setName(String name) {
//条件语句控制输出 如果对象中的name长度在3~5,输出
if(name.length()>=3&&name.length()<=5){
this.name =name;
}
}
package com.feifan.javaoop.Day3;
public class PrivateTest {
public static void main(String[] args) {
Private p = new Private();
p.setName("sssssss"); //输出null 因为长度大于5了
System.out.println(p.getName());
}
}
②如何访问private修饰的方法?
在什么情况下需要私有化方法?
比如:windows文件窗口可以同时创建多个,但是windows任务管理器窗口只能创建一个。只能创建一个这种情况怎么解决?——使用单例模式
单例模式:一种模板, 解决在一个程序中只能有一个对象的问题。
Java中共23种模板,解决问题
那具体如何实现 单例模式?——对构造方法私有化
因为每创建一个对象,就要写一个构造方法,所以对构造方法私有化后,外部就不能新创建类了
所以通过 getXXX () return ; 向外提供一个方法,用来创建唯一的一个对象,并返回此对象
package com.feifan.javaoop.Day3;
public class WindowDemo {
static WindowDemo windowDemo;
private WindowDemo(){
//将构造方法私有了 ,其他类就不能创建对象了
}
//向外提供一个方法,用来创建唯一的一个对象,并返回此对象
public static WindowDemo getWindowDemo(){ //static 修饰的属性、方法可以通过类名调用
if(windowDemo == null){
//没有调用getWindowDemo()时返回为null,调用后输出om.feifan.javaoop.Day3.WindowDemo@1b6d3586 是哈希code值 地址
windowDemo = new WindowDemo();
}
return windowDemo;
}
}
package com.feifan.javaoop.Day3;
public class TestWindow {
public static void main(String[] args) {
System.out.println(WindowDemo.getWindowDemo());
// 输出om.feifan.javaoop.Day3.WindowDemo@1b6d3586 是哈希code值 地址
}
}
是一种设计思想,是实现代码重用和程序扩展的一种方式。
代码重用:super.play();
super调用父类的play方法,实现代码重用。
程序:方法重写 @Override
父类方法不能满足,子类重写,对程序进行了
在Java中:
用extends 关键字表示继承关系。子类 extends 父类
不支持多继承,一个类只有一个直接父类
继承后 ,子类可以调用父类中的所有非私有的属性、方法
比如:
说"猫是动物",“狗也是动物”
传递性: C extends B, B extends A
那么C类具有 B类 和A类 的所有非私有的属性和方法。
当一个类没有继承任何类时,JVM默认类继承Object类
Object类是默认的基类
派生类–子类 父类–基类
派生类 extends 基类
子类构造方法会先调用父类构造方法 。
创建一个子类,子类要初始化前先要给父类初始化
使用super关键字调用父类任意一个构造方法,必须卸在构造方法第一行
比如 : 哮天犬 extends 狗 ,狗 extends 动物 ,在test类中,要new 一个哮天犬类,得在哮天犬类中写构造方法,super()必须写在第一行,因为要通过super()调用狗的构造方法,同理,狗中的构造方法第一行要写super()来调用动物的构造方法。
//构造方法
public Animal(){
super();
}
//构造方法
public Dog(){
super();
}
//构造方法
public AngelDog(){
super();
}
super 误区:
super.play(); 通过super调用父类中的play方法,这里 super 指的不是父类对象,而是在创建子类时,把父类中的非私有的属性、方法加载到子类对象中,并不会创建父类。
子类继承父类时,继承过来的方法不能满足自身需求,就可以重写方法。
方法重写就是把父类中的方法框架拿过来,里面的功能按照子类需求重写。
规则:
注意:
@Override 是java中提供的一种注解标签,放在方法上面,表示方法是从父类重写而来,就会对其语法校验(@Override 在编译期间校验)。
方法重写:
父类方法不能满足子类需求,子类重写方法功能。
重写的方法和父类中的方法名、参数、返回值都相同,
重写方法访问权限必须>=父类
方法重载:
方法功能,
方法名相同,但参数(类型、顺序、个数)不同的多个方法
比如:max(int x,int y) 和 max(double x,double y)
abstract 修饰的类 、方法
可以没有具体实现,只是定义类、方法,用在顶层设计
一个抽象类里可以没有抽象方法,但一个类里有抽象方法,那它一定是抽象类
抽象方法怎么用? 在设计层面使用(父类),继承关系中使用
比如:
public abstract class Animal {
/*
抽象方法
abstract 修饰的方法是具体方法, 可以没有具体实现
只是作为一个功能定义,在顶层类中往往需要定义功能,让其他类去实现
*/
/*
代码省略
*/
public abstract void eat();
}
public abstract class Dog extends Animal {
/*
抽象类中可以没有抽象方法
*/
/*
代码省略
*/
//Dog子类具体实现继承父类的eat方法
public void eat() {
System.out.println("狗吃食物");
};
}
package com.feifan.javaoop.Day4;
public class AngelDog extends Dog {
/*
代码省略
*/
@Override //对父类继承的eat方法重写
public void eat() {
super.setName("");
super.getName();
System.out.println("哮天犬坐着吃");
}
}
package com.feifan.javaoop.day4.polymorphic;
public class Test1 {
public static void main(String[] args) {
Dog dog = new Dog();//Dog的引用指向Dog对象
Cat cat = new Cat();
dog.eat();
/*
编译期间: 写代码时就是编译期间, Animal dog1在编译期间是Aniaml类型
运行期间: run运行程序,Animal dog1 在运行期间类型是Dog类型
*/
/*
对于成员方法来讲 编译看左边,运行看右边
对于静态方法,编译和运行都看左边
对于成员变量,编译和运行都看左边
*/
Animal dog1 = new Dog();
dog1.eat();
dog1.sleep();
Animal cat1 = new Cat();
cat1.eat();
cat1.sleep();
}
}
package com.feifan.javaoop.day4.polymorphic;
public class Test2 {
public static void main(String[] args) {
/*
我们创建一个喂不同的动物,动物吃东西
先不用多态来实现
*/
Dog dog=new Dog();
Cat cat=new Cat();
Test2 t = new Test2();
t.feedDog(dog);
t.feedCat(cat);
}
public void feedDog(Dog dog){
System.out.println("喂狗 ");
System.out.println("狗吃 ");
dog.eat();
}
public void feedCat(Cat cat){
System.out.println("喂猫 ");
System.out.println("猫吃 ");
cat.eat();
}
}
package com.feifan.javaoop.day4.polymorphic;
public class Test3 {
public static void main(String[] args) {
/*
我们创建一个喂不同的动物,动物吃东西
用多态来实现
把子类类型上升为父类类型 可以用父类类型表示所有的子类对象
*/
Animal dog=new Dog();
Animal cat=new Cat();
Test3 t = new Test3();
t.feedAnimal(dog);
t.feedAnimal(cat);
}
/*
多态提高了程序的扩展性 valueOf(Object obj)
多态存在不足: 使用多态时,不能访问子类中特有的方法, 因为已经向上转为父类类型了,编译期间不能调用子类特有方法
解决: 需要向下转型
*/
public void feedAnimal(Animal animal){
animal.eat();
//向下类型转换时需要做一个判断
// animal instanceof Dog 检测animal在运行时 实际的类型是否为Dog ,如果是返回true,否则false
if(animal instanceof Dog){ // 实例 instanceof
Dog dog = (Dog)animal;
dog.play(); //可以访问子类中的特有play方法了
}
}
}
多态存在条件:
继承
重写
父类引用指向子类 Animal Dog = new Dog();
向上转型: 子类提升为父类
Animal x=new Cat() //向上转型,Cat对象提升到Animal对象
x.eat() //只能使用父类中的方法
x.look() //报错!父类对象不能使用子类中的方法
向下转型: 父类对象强制变为子类对象
Animal x=new Cat()
Cat m=(Cat)x; //向下转型
m.eat() ;
m.look();//子父类中的方法都可以使用
//向下类型转换时需要做一个判断
// animal instanceof Dog 检测animal在运行时 实际的类型是否为Dog ,如果是返回true,否则false
if(animal instanceof Dog){ // 实例 instanceof
Dog dog = (Dog)animal;
dog.play(); //可以访问子类中的特有play方法了
}