一:面向对象三大特性
面向对象三大特性:封装、继承、多态
1.1 封装
封装的必要性:
在对象的外部为对象属性赋值,可能存在非法数据的录入;
就目前的技术而言,并没有办法对属性的赋值加以控制。
概念:尽可能隐藏对象的内部实现细节,控制对象的修改及访问权限
访问修饰符:private(可将属性修饰为私有,仅本类可见)
公共访问方法:使用private修饰符后,外部想要访问属性时则需要提供公共的方法方法。以公共访问方法的形式,对属性就行赋值和取值操作。但是依旧没能控制数据的正确录入。
过滤有效数据:为了保证数据的正确录入,可在公共的访问方法内部添加判断逻辑,从而过滤掉非法数据。
public class Test {
public static void main(String[] args) {
People s1 = new People();
s1.name = "张三";
//s1.age = 2000;//这样赋值不合常理,一个人的年龄不应该出现2000岁,私有属性不能直接访问
s1.setAge(20);//通过公共访问方法赋值
System.out.println(s1.getAge());//通过公共方法取值
}
}
class People{
String name;//姓名
private int age; //年龄
//公共访问方法
public int getAge() {
return age;
}
public void setAge(int age) {
//过滤有效数据
if(age > 0 && age <= 140) {
this.age = age;
}else {
this.age = 18;
}
}
}
1.2 继承
概念:继承时类与类之间特征和行为的一种赠与或获得。
父类的选择:可根据程序的需要从使用到的多个具体类中,进行共性抽取,从而定义父类。
语法:class 子类 extends 父类{ }//定义子类时,显示继承父类。
应用:产生继承关系之后,子类可以使用父类中的属性和方法,也可以定义独有的属性和方法。
好处:既提高了代码的复用性,又提高了代码的可扩展性。
特点:Java为单继承,一个类只能有一个直接父类,但可以多级继承,属性和方法逐级叠加。
不可继承:
构造方法:类中的构造方法只负责创建本类对象,不可继承;
private修饰的属性和方法:私有的属性和方法只能本类可见;
default所修饰的属性和方法当父类和子类不在同一包中时不可继承。
1.3 多态
概念:父类引用指向子类对象,从而产生多种形态。
父类引用仅可调用父类所声明的属性和方法,不可调用子类独有的属性和方法。当子类重写了父类中的方法时,以父类类型引用调用此方法,优先执行子类中重写后的方法。
多态的应用:
方法重载可以解决接收不同对象参数的问题,但是随着子类的增加,本类需要提供大量的方法重载,多次修改并重新编译源文件,代码的耦合度太高。此时就可使用多态。
(1) 使用父类作为方法形参实现多态,使方法参数的类型更为宽泛;
(2)使用父类作为方法返回值实现多态,使方法可以返回不同子类对象。
二: 三个关键字(abstract、static、final)
2.1 abstract关键字
抽象类:abstract所修饰类即为抽象类,抽象类不能new对象,但是可以声明为引用。
抽象类的作用:
(1).可被子类继承,提供公共的属性和方法。
(2).可声明为引用,更自然的使用多态。
抽象方法:abstract所修饰的方法即为抽象方法,抽象方法只有方法声明,没有方法实现({ }的部分);意为不完整的方法,必须包含在抽象类中。
在类的继承关系中,如果子类不是抽象类,那么子类必须实现父类中的所有抽象方法。
public class TestAnimal {
public static void main(String[] args)
{
//Animal animal=new Animal(); 抽象类不能new 编译报错
Animal dog=new Dog(); //抽象类声明为引用
Animal cat=new Cat();
dog.eat();
cat.eat();
}
}
//动物类 (抽象类)
abstract class Animal {
String breed;//品种
int age;//年龄
String sex;//性别
//吃(抽象方法)
public abstract void eat();
//睡
public void sleep() {
System.out.println("动物睡...");
}
}
//狗狗类
class Dog extends Animal{
@Override // 子类不是抽象类时,必须实现父类的所有抽象方法
public void eat() {
System.out.println("狗在吃骨头");
}
}
//猫咪类
class Cat extends Animal{
@Override // 子类不是抽象类时,必须实现父类的所有抽象方法
public void eat() {
System.out.println("猫在吃鱼");
}
}
2.2 static关键字
实例属性(实例变量):实例属性是每个对象各自持有独立的空间(多份),对象单方面的修改不会影响其他对象。
静态属性(静态变量):静态属性是整个类共同持有的共享空间(一份),任何对象修改都会影响其他对象。
静态(static):可以修饰属性和方法,称为静态属性(类属性)、静态方法(类方法);静态成员是全类所有对象共享的成员,在全类中只有一份,不会因创建多个对象而产生多份;不必创建对象可直接通过类名访问。
静态方法的特点:象共静态方法允许直接访问静态成员;静态方法不能直接访问非静态成员;静态方法中不允许使用this和super关键字;静态方法可以继承,不能重写,没有多态。
动态代码块:创建对象时,触发多态代码块的执行。执行地位:初始化属性之后、构造方法之前。作用:可为实例属性赋值,或必要的初始行为。
静态代码块:类在第一次被加载时会调用静态代码块(只会执行一次)
2.3 final关键字
可修饰的内容:类(最终类),方法(最终方法),变量(最终变量)
final所修饰的类不能被继承;如:String、Math、System都是final修饰的类,都不能被继承。
final所修饰的方法不能被覆盖,不支持子类以覆盖的形式修改。
final所修饰的变量是常量,只能初始化一次,其值不能改变。
常量(实例常量和静态常量)不再提供默认值,必须手动赋予初始值
三: 接口
概念:接口相对于特殊的抽象类,定义方式、组成部分与抽象类类似。使用interface关键字定义;
特点:没有构造方法,不能创建对象;只能定义:公开静态常量,公开抽象方法;
和抽象类的异同:
相同点:可编译成字节码文件;不能创建对象;可以作为引用类型;具备Object类中所定义的方法。
不同点: 接口所有属性都是公开静态常量,隐式使用public static final修饰;
接口所有方法都是公开抽象方法,隐式使用public abstract修饰;
接口没有构造方法、动态代码块、静态代码块。
任何类在实现接口时,必须实现接口中所有的抽象方法,否则此类为抽象类;实现接口中的抽象方
法时,访问修饰符必须是public;接口可声明为引用,并指向实现类对象。
接口实现多态:使用接口作为方法的参数和返回值,实际赋值使用实现类对象,从而实现多态。
接口常见关系:
类与类之间,子类只能继承(extends)一个父类,即Java的单继承;
类与接口之间:类可以实现(implements)多个接口,即多实现;
接口与接口之间:接口可以继承(extends)多个接口,即接口多继承。
常量接口:将多个常用于表示状态或固定值的变量,以静态常量的形式定义在接口中统一管理,提
高代码的可读性。
宏观接口:接口是一种标准、规范。
回调原理:先有接口的使用者,后有接口的实现者。
接口好处:程序的耦合度降低;更自然地使用多态;设计与实现完全分离;更容易搭建程序框架;更容易更换具体实现。
四:常用类
4.1 内部类
分类:成员内部类;静态内部类;局部内部类;匿名内部类。
4.1.2 成员内部类
概念:在一个类的内部再定义一个完整的类。
特点:
编译之后可生成独立的字节码文件;
内部类可直接访问外部类的私有成员,而不破坏封装;
可为外部类提供必要的内部功能组件。
注意:
成员内部类在类的内部定义,与实例变量、实例方法在同一级别;
外部类的一个实例部分在创建内部类对象时,必须依赖外部类对象;如下:
Outer out = new Outer(); Outer.Inner in = out.New Inner();
当外部类和内部类存在重名属性时,会优先访问内部类对象;
成员内部类不能定义静态成员。
4.1.2 静态内部类
静态内部类不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员;
只能直接访问外部类的静态成员(实例成员需实例化外部类对象);
Outer.Inner inner = new Outer.Inner(); Outer.Inner.how();
4.1.3 局部内部类
定义在外部类方法中,作用范围和创建对象范围仅限于当前方法;
局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final;
局部内部类用来限制类的使用范围。
4.1.4 匿名内部类
没有类名的局部内部类(一切特征都于局部内部类相同);
必须继承一个父类或实现一个接口;
定义类、实现类、创建对象的语法合并,只能创建一个该类对象;
优点:减少代码量;
缺点:可读性较差。
使用匿名内部类具体代码如下(Usb为接口):
Usb usb = new Usb(){
@Override
public void service(){
System.out.println("连接电脑成功,鼠标正常使用");
}
};
4.2 Object类
超类、基类,所有类的直接或间接父类,位于继承树的最顶层;
任何类如果没有书写extends显示继承某个类,都默认直接继承Object类,否则间接继承;
Object类中所定义的方法,是所有对象都具备的方法;
Object类型可以存储任何对象,作为参数可以接收任何对象,作为返回值可返回任何对象;
常用方法有:getClass();hashCode();toString();equals();
方法代码说明如下:
package com.shuman.work6;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
Person p1 = new Person();
Person p2 = new Person();
p1.hight = "176";
p1.name = "张三";
p1.sex = "男";
p2.hight = "170";
p2.name = "李四";
p2.sex = "女";
System.out.println( p1.equals(p2) );//指示其他对象是否“相等”
System.out.println("p1的哈希值:" + p1.hashCode());
System.out.println("p2的哈希值:" + p2.hashCode());
System.out.println("p1对象的字符串表现形式:" + p1.toString());
System.out.println("p2对象的字符串表现形式:" + p2.toString());
Class c1 = p1.getClass(); //获取class对象
Class c2 = Class.forName("com.shuman.work6.Person");//获取class对象
Object obj = c1.newInstance();//获取一个Person对象
//c1.getDeclaredMethod(name, parameterTypes)
Method[] m = c1.getDeclaredMethods();//获得本类的所有方法
System.out.println("======");
for (Method method : m) {
System.out.println(method);
}
System.out.println("=====");
Method met = c1.getMethod("fun",null);//获得fun函数对象
met.invoke(obj, null);//执行fun函数
}
}
class Person {
String name; //姓名
String hight;//身高
String sex; //性别
public void fun() {
System.out.println("Person的一个方法");
}
}
有如下的输出: