1.面向对象
1,面向对象的特征
- 封装:保护内部的操作不被破坏;
- 继承:在原本的基础之上继续进行扩充;
- 多态:在一个指定的范围之内进行概念的转换。
2,类和对象
生活中,先有对象再根据对象的属性和行为抽取出类
类:确定对象将拥有的特征(属性)和行为(方法);— 抽象的概念/模板
对象:类的实例表现;— 具体实体
属性:对象所具有的各种静态特征(对象有什么)
方法:对象具有的各种动态行为(对象能做什么)
实例化:就是 类----new----对象
(声明对象) (实例化对象)
声明对象:在内存的栈空间里,开辟了一块区域 取名为one(可以为自定义变量名称),这时里边是空,这时进行属性和方法的调用是不被允许的;
实例化对象:在内存的堆空间里,完成具体对象的初始化操作
对象的引用传递,实际上传递的是堆内存空间的使用权
栈:被调用时处于存储空间中,调用完毕后立即释放;(一般存放变量名)
堆:由java垃圾回收机制决定;(一般存放对象)
注意事项:类中定义的方法–成员方法,类中定义的属性变量–成员变量(系统会给出默认初始值),方法中的属性–局部变量(必须指定默认值)
引用类型对象的初始值是null
程序中,先有类,再通过创建出实例对象
类
class Person{
//类名首字母大写,大驼峰命名 UserName
//属性 -- 成员变量 特点:有默认值 java中没有全局变量的概念
/*
String null
int 0
double 0.0
boolean false
char ''
访问修饰符:
public private protected default 缺省的
基本数据类型
整数类型 内存大小
byte 1
short 2
int 4
long 8
浮点类型
float 4
double 8
字符类型
char 2
布尔类型
boolean 1
*/
public String name; //小驼峰命名
//方法
public void methodName(int aaaa){
int a = 0; //局部变量 ,必须要附初始值
int b = a+1;
}
}
3,构造方法
Person p = new Person();
//Person 构造方法名()
//特点:没有返回值类型,方法名和类名相同
每一个类都会有一个默认的无参构造方法
当写一个有参构造时,无参构造会消失。
//作用,实例化对象
给属性赋初始值
不能被对象单独调用,只能在对象实例化new的时候被调用,不能使用类.方法名调用;
4,this关键字
this.方法名( ) / this.属性名,引用当前对象的成员;
this:当前对象的默认引用
this的使用:调用成员变量,解决成员属性和局部变量同名冲突
在构造方法中,使用this关键字调用其他构造方法,位置只能放在方法第一条语句;
5,重载
参数列表不同包括:个数不同、类型不同和顺序不同
跟成员方法一样,构造方法(构造器)也可以重载。
声明为final的方法不能被重载。
声明为static的方法不能被重载,但是能够被再次声明
6,static关键字
静态方法不可调用常态的方法
常态方法可以调用静态方法
2.继承
1,继承(extends)
extends:延伸 拓展
继承:子类继承父类,拥有父类的属性和方法。
public class Animal {
public String name;
public String sex;
}
class Dog extends Animal{
}
Dog dog = new Dog();
特点:
1,继承父类的属性和方法
2,不能继承父类的
private 修饰的属性和方法
父类的构造方法
子类和父类不在同一包下,使用默认的访问修饰符
3,java中的类只有单继承,一个子类只有一个父类。但是可以多重继承
4,一个类如果没有extends继承,默认继承Object。Object是所有类的父类
5,父类又叫超类,基类。子类又叫派生类。
2,方法的重写
当父类的方法满足不了子类的需求,这个时候需要子类重写父类的方法
特点:方法名和父类的方法名一致,返回值类型一致,参数列表一致,
子类方法的访问权限不能比父类的更严格。
子类的返回值可以是父类返回值对象的子类对象
基本数据类型 不是面向对象的,但是提供了八种包装类型。
int Integer
double Double
float Float
char Character
3,super关键字
super:表示对父类对象的引用
super(); 调用父类的无参构造 必须写在构造方法中的第一行
super只能出现在子类的方法和构造方法中
super调用构造方法时,只能是第一句
super不能访问父类的private成员
3.多态
1,重写
当父类的方法满足不了子类的需求,这个时候需要子类重写父类的方法
特点:方法名和父类的方法名一致,返回值类型一致,参数列表一致,
子类方法的访问权限不能比父类的更严格。
2,继承
特点:
1,继承父类的属性和方法
2,不能继承父类的
private 修饰的属性和方法
父类的构造方法
子类和父类不在同一包下,使用默认的访问修饰符
3,java中的类只有单继承,一个子类只有一个父类。但是可以多重继承
4,一个类如果没有extends继承,默认继承Object。Object是所有类的父类
5,父类又叫超类,基类。子类又叫派生类。
3,构造方法
特点:没有返回值类型,方法名和类名相同
每一个类都会有一个默认的无参构造方法
当写一个有参构造时,无参构造会消失。
实例化对象:给属性赋初始值
不能被对象单独调用,只能在对象实例化new的时候被调用,不能使用类.方法名调用
4,this关键字
this.方法名( ) / this.属性名,引用当前对象的成员;
this:当前对象的默认引用
this的使用:调用成员变量,解决成员属性和局部变量同名冲突
在构造方法中,使用this关键字调用其他构造方法,位置只能放在方法第一条语句
5,重载
参数列表不同包括:个数不同、类型不同和顺序不同
跟成员方法一样,构造方法(构造器)也可以重载。
声明为final的方法不能被重载。
声明为static的方法不能被重载,但是能够被再次声明
6,final及static关键字
- 修饰成员变量
- 修饰成员方法
- 修饰类
8,super关键字
super:表示对父类对象的引用
super(); 调用父类的无参构造 必须写在构造方法中的第一行
super只能出现在子类的方法和构造方法中
super调用构造方法时,只能是第一句
super不能访问父类的private成员
2,多态的使用
形成多态的必要条件
1,要有关系–继承
2,要有方法重写–重写式多态
3,要有向上转型–父类的引用指向子类的对象
public class Animal {
public void eat(){
System.out.println("animal eatting...");
}
}
public class Cat extends Animal{
public void eat(){
System.out.println("我吃鱼");
}
}
public class Dog extends Animal{
public void eat(){
System.out.println("我吃骨头");
}
public void run(){
System.out.println("我会跑");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Cat(); //向上转型 指向 指针
animal.eat();
Cat cat = (Cat)animal; //向下转型
int 4 double 8
int a = 1;
double d = a;
int c = d;
animal = new Dog();
animal.eat();
}
}
//结果:
//我吃鱼
//我吃骨头
3,向上转型
这就是向上转型,Animal animal = new Cat(); 将子类对象 Cat 转化为父类对象 Animal。这个时候 animal 这个引用调用的方法是子类方法。
转型过程中需要注意的问题
- 向上转型时,子类单独定义的方法会丢失。比如上面Dog类中定义的run方法,当animal引用指向Dog类实例时是访问不到run方法的,
animal.run()
会报错。 - 子类引用不能指向父类对象。
Cat c = (Cat)new Animal()
这样是不行的。
向上转型的好处
- 减少重复代码,使代码变得简洁。
- 提高系统扩展性。
4,向下转型
与向上转型相对应的就是向下转型了。向下转型是把父类对象转为子类对象
//还是上面的animal和cat dog
Animal a = new Cat();
Cat c = ((Cat) a);
c.eat();
//输出 我吃鱼
Dog d = ((Dog) a);
d.eat();
// 报错 : java.lang.ClassCastException:com.chengfan.animal.Cat cannot be cast to com.chengfan.animal.Dog
Animal a1 = new Animal();
Cat c1 = ((Cat) a1);
c1.eat();
// 报错 : java.lang.ClassCastException:com.chengfan.animal.Animal cannot be cast to com.chengfan.animal.Cat
为什么第一段代码不报错呢?相比你也知道了,因为 a 本身就是 Cat 对象,所以它理所当然的可以向下转型为 Cat,也理所当然的不能转为 Dog,你见过一条狗突然就变成一只猫这种操蛋现象?
而 a1 为 Animal 对象,它也不能被向下转型为任何子类对象。比如你去考古,发现了一个新生物,知道它是一种动物,但是你不能直接说,啊,它是猫,或者说它是狗。
向下转型注意事项
-
向下转型的前提是父类对象指向的是子类对象(也就是说,在向下转型之前,它得先向上转型)
-
向下转型只能转型为本类对象(猫是不能变成狗的)。
5,经典实例
class A { public String show(D obj) { return ("A and D"); } public String show(A obj) { return ("A and A"); } } class B extends A{ public String show(B obj){ return ("B and B"); } public String show(A obj){ return ("B and A"); } } class C extends B{ } class D extends B{ } public class Demo { public static void main(String[] args) { A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println("1--" + a1.show(b)); A and A System.out.println("2--" + a1.show(c)); A and A System.out.println("3--" + a1.show(d)); A and D System.out.println("4--" + a2.show(b)); System.out.println("5--" + a2.show(c)); System.out.println("6--" + a2.show(d)); System.out.println("7--" + b.show(b)); System.out.println("8--" + b.show(c)); System.out.println("9--" + b.show(d)); } } //结果:
4.接口
口的特性
1,接口没有构造方法,不能实例化
2,接口中允许有哪些成员
1,共有的静态常量 public static final String NAME="";
public static final 修饰符都是隐式的
2,方法
jdk1.8 前 只能有抽象方法
public abstract void method();
public abstract 修饰符都是隐式的
jdk1.8 后 还可以有默认方法和静态方法
public default void method(){
}
public static void method(){
}
jdk1.9 后 可以有私有方法
private void method(){
}
3,接口不能实例化,只能被子类实现或者接口继承
class Door implements Lock{
//Door类 实现了 Lock接口
}
4,实现接口必须重写(实现)接口中的方法,或者子类是抽象类
5,接口和接口之间继承关系(接口中的继承是多继承,多个继承接口之间用逗号隔开)
public interface TestInterFace2 extends TestInterface,Lock{
}
6,类实现接口可以是多实现
public class Door implements Lock,TestInterface {
}
7,一个类可继承的同时实现接口 先继承再实现
public class FdDoor extends Door implements Lock {
}