Java面向对象主要内容包括类和对象,面向对象的三大特性—封装、继承、多态。抽象类和接口。下面依次介绍。
一、类和对象
1、基本概念
类:是抽象的,是具有相同属性和方法一组对象的集合。类是一种自定义的数据类型
对象:是具体的,是描述客观事物的一个实体
2、类图
常用工具:Rose 、Visio
举例: Dog
+name:String //属性名 类型
-health:int //+:public -:private
+print( ) : void //方法名 返回值类型
3、类的方法
举例:public void play(){ }
private String getName(){return name}
无返回值 用void 有返回值 用int String等,必须使用关键字return
无参:方法名后()无参数 有参:方法名后()有参数
形参:定义的参数 方法后有{} 实参:调用的参数,方法后无{}
参数传递:要保证数据类型一致;顺序一致; 由实参单向传递给形参
4、方法调用
- 在同类里无需创建对象直接调用,在其他类需要创建类对象。
- Static静态方法,可以通过类名调用,无需创建类对象
- 当输出一个对象时,会自动调用一个toString()方法
5、构造方法
作用:对象初始化 系统提供默认无参构造方法
举例:public Person(){this.name=”a”} 无参构造
public Person(String name){this.name=”a”} 有参构造
特点:方法名和类名相同;
无返回值类型
可以指定参数
6、方法重载
特点:同一个类中
方法名相同
参数个数或类型不同
与返回值、访问修饰符无关
注意:构造方法的重载,由于此时系统不再提供默认无参构造方法,需要重新书写
7、成员变量、局部变量
成员变量:在类中声明,在整个类中使用。有初始值 null
局部变量:在方法、代码体内声明,局部使用。无初始值
局部变量和成员变量同名的时候,局部变量具有更高的优先级
8、静态变量、实例变量
实例变量(也是成员变量)在类中声明,没有被static修饰。每创建一个实例,就会为实例变量分配一次内存。
静态变量(也是类变量)被static修饰的成员变量,通过类名直接访问会在内存中只有一个拷贝,优先占有空间,能被所有对象共享。
9、Java中栈和堆
堆内存用来存放由new创建的对象和数组,
栈内存用来存储基本类型的变量,常量,对象的引用变量。栈中的变量指向堆内存中的变量,又称为java的指针。
举例:int i=1;
String s = new String( “Hello World” );
变量i和s以及1存放在栈内存,而s指向的对象”Hello World”存放于堆内存。
10、this关键字
表示调用当前类中的成员变量和方法
注意:成员变量和局部变量同名,必须使用this关键字
在类的构造方法中,通过this调用重载的构造方法,必须是该构造方法的第一条语句
11、访问修饰符
访问级别从大到小:
public(任何地方)> protected(本类、本包、子类)
默认(本类、本包)> Private(本类)
Static修饰符:用来修饰成员变量、方法和代码块
静态变量和方法可以通过类名访问,静态代码块JVM加载类时自动执行
二、封装、继承、多态
1、封装
将类的状态信息隐藏在类的内部,不允许外部程序直接访问,但可以提供接口、方法来访问,防止被误操作。解决代码隐藏的问题
封装的体现:属性隐藏;包机制;
属性隐藏:修饰符改为private,设置getter/setter方法
包机制:类似创建文件夹,易于查找和管理。
定义包:package com.irunker.demo
导入包:import java.until.Date;
2、继承
子类继承父类的属性和方法,解决代码重用的问题
举例:public class Dog extends Pet{ }
特点:一个类只能有一个直接父类
子类不能继承private修饰的属性和方法
子类与父类是is-a关系
Object顶级父类:
所有java类都直接或间接的继承Object类
常用的方法:hashCode() getClass() equals() toString() clone()
3、super、final关键字
super关键字
1、Super代表父类对象,可调用父类对象的属性和方法
2、在子类构造方法中调用且必须是第一句
3、无法访问private的成员
final关键字
(1)最终的意思,可以用于修饰类,方法,变量
(2) final修饰的类不能被继承。
final修饰的方法不能被重写。
final修饰的变量是一个常量。只能被赋值一次。
4、继承下构造方法调用规则
1、当子类构造方法没有用this\super显式调用,会自动调用父类无参构造方法
2、一旦父类使用带参构造方法,将会覆盖默认的无参构造方法。所以必须写无参构造方法
3、子类构造方法使用显式调用,则只调用的是父类有参构造方法,写法:super(name);
5、方法重写:
1、首先用super.方法的方式来保留父类的方法内容,可以继续添加其他方法内容
2、子类根据需求对从父类继承的方法进行重写,覆盖掉父类的方法。
3、构造方法不能重写
重写规则:
1、方法名、参数相同 2、父类声明、子类重写方法
区别:方法重载:同类、同名不同参 方法重写:不同类、同名也同参
6、多态
同一个引用类型,使用不同的实例,执行不同的操作
举例:Pet pet = new Dog()实例化一个子类对象。父类引用指向子类对象,子类完成向上转型,得到的对象可以直接调用子类方法
方法重写是实现多态的基础。解决代码的可扩展性问题
实现多态步骤:1、继承/实现接口 2、重写 3、向上转型
多态的应用:1、使用父类作为方法的形式参数 2、使用父类作为方法的返回值类型。静态绑定(引用成员变量、静态方法);动态绑定(引用重写后的方法)
7、向上转型与向下转型
向上转型:父类型 变量=new 子类型(); Pet pet=new dog();
父类引用变量指向子类对象,自动进行类型转换。
通过父类引用变量可以直接调用子类方法,但无法调用子类特有方法。
向下转型:子类型 变量=(子类型)父类型; Dog dog=(Dog)pet;
父类类型转换为具体的子类类型,需要强制类型转换。
解决无法调用子类特有方法的问题。
为减少向下类型转换异常,使用instanceof运算符进行类型判断是否是是特定类的一个实例
三、抽象类与接口
1、抽象类与抽象方法
普通方法:
举例:public void work(){//方法体}
特点:有方法体、无abstract
抽象方法: 注意接口的抽象方法 可以不写public abstract
举例:public abstract void print();
特点:无方法体,有abstract;必须在抽象类里;必须在子类实现、否则子类必须被定义为抽象类
普通类:
修饰符 class 类名(){ … }
普通类可以被实例化(创建对象)
抽象类:
修饰符 abstract class 类名{ }
1、可以有非抽象的构造方法,在子类实例中调用;但一定没有抽象构造方法,也没有抽象静态方法 public abstract Base(){} X
2、抽象类里一般有抽象方法,也可以没有抽象方法。抽象类不允许实例化(创建对象),接口也是一样。如:Pet pet=new Pet(); X
2、接口
用interface修饰的一个不可实例化的类
创建:
public interface usbInterface extends Io1,Io2{//接口继承父接口
void sevice(); //抽象方法,默认是的abstract、public的,一般不写 }
实现:
public class MyClass extends Base implements Io1,Io2{//继承父类实现接口 }
特性:
接口没有构造方法,不可被实例化,常作为类型使用
一个类必须实现接口的所有方法,除非这个类是抽象类;接口可以继承多个接口
接口中的变量都是静态变量(public static final),必须显式初始化
接口的使用:
接口中的成员变量:默认都是public static final的,必须显式初始化
接口中的方法:默认都是public abstract的
使用原则:
接口做系统和外界的交互、
接口一旦制定,不可修改
抽象类可以完成部分功能实现
3、抽象类与接口
类似于 鸟-抽象类 鸟叫-接口
1、抽象类只能单继承,接口可以多实现
2、抽象类被继承是”is a”关系; 接口被实现是”like a、has a “关系
3、抽象类中定义的是继承体系中的共性功能。接口中定义的是继承体系中的扩展功能。
4、抽象类有构造方法,可以是变量、非抽象方法。接口成员变量是常量,都是抽象方法,却没有构造方法。
4、面向对象设计的原则
1、摘取代码中变化的行为,形成接口
2、多用组合,少用继承
3、针对接口编程,不依赖于具体的实现
4、针对扩展开放,针对改变关闭
5、关于is-a has-a ,like-a
- is-a,顾名思义,是一个,代表类的继承关系。子类继承父类
如果A is-a B,那么B就是A的父类。
一个类完全包含另一个类的所有属性及行为。
Ag 狗是一种动物;猫是一种动物
- has-a,顾名思义,有一个,代表从属关系。对象从属于类
如果A has a B,那么B就是A的组成部分。
同一种类的对象,通过它们的属性的不同值来区别。
Ag 狗有一个名字 计算机有一个操作系统。
- like-a,顾名思义,像一个,代表组合关系。
如果A like a B,那么B就是A的接口。
新类型有老类型的接口,但还包含其他函数,所以不能说它们完全相同。
Ag 计算机有一个USB接口 空调有一个实现加热的接口
6、异常处理
常见异常:
NumberFormatException数字格式转换异常
InputMismatchException:数据类型不匹配异常
Arithmetic Exception:算数异常(/by zero)
Nullpointer Exception:空指针异常(访问null对象成员)
ClassCastException:对象强制类型转换出错
JAVA异常处理机制:
1、Try-catch
2、Try-catch-finally finally代码块总被执行,除非执行System.exit(1)才中断。即使出错,遇到return,也要完成finally代码块的操作
3、try-catch-catch多重catch: 有顺序的(先子类后父类Exception)
4、throw抛出异常,位于方法体内
5、throws声明一个或多个异常,位于方法参数列表后面 方式:调用者处理异常,继续抛出异常
6、自定义异常 SexExcepetion extends Exception
四 、相关代码
- package com.hfxt.demo03;
- public class School {
- private String name;
- private Printer printer;
- public School(){}
- public School(String name, Printer printer) {
- super();
- this.name = name;
- this.printer = printer;
- }
- public void setPrinter(Printer printer) {
- this.printer = printer;
- }
- public void printing(String content){
- if(printer==null){
- System.out.println(“暂时没有配置打印机”);
- }else{
- printer.print(content);
- }
- }
- }
- package com.hfxt.demo03;
- public class Printer {
- private String brand;
- private double price;
- public Printer(){}
- public Printer(String brand, double price) {
- super();
- this.brand = brand;
- this.price = price;
- }
- public void print(String content){
- System.out.println(content+“ ”+this.brand+“ ”+this.price);
- }
- }
- package com.hfxt.demo03;
- public class ColorPrinter extends Printer{
- public ColorPrinter() {
- super();
- // TODO Auto-generated constructor stub
- }
- public ColorPrinter(String brand, double price) {
- super(brand, price);
- // TODO Auto-generated constructor stub
- }
- @Override
- public void print(String content) {
- System.out.println(“彩色打印”);
- super.print(content);
- }
- }
- package com.hfxt.demo03;
- public class BlackPrinter extends Printer{
- public BlackPrinter() {
- super();
- // TODO Auto-generated constructor stub
- }
- public BlackPrinter(String brand, double price) {
- super(brand, price);
- // TODO Auto-generated constructor stub
- }
- @Override
- public void print(String content) {
- System.out.println(“黑白打印”);
- super.print(content);
- }
- }
- package com.hfxt.demo03;
- public class Test {
- public static void main(String[] args) {
- School school = new School();
- school.printing(“123”);
- /*Printer printer = new BlackPrinter(“ph”, 3);
- school.setPrinter(printer);
- school.printing(“123”);
- printer=new ColorPrinter(“canon”, 3.5);
- school.setPrinter(printer);
- school.printing(“321”);*/
- Printer printer = new BlackPrinter(“ph”, 3);
- printer.print(“abc”);
- printer=new ColorPrinter(“canon”, 3.5);
- printer.print(“123”);
- }
- }
- package practice;
- /**
- *
- * @author Visant
- *定义形参,调用实参;值传递、引用传递;传递方向:实参到形参,单向的;
- *注意引用传递:引用堆地址,结果随变量值变化而变化
- *无参、有参;有无返回值方法的学习
- *引用数据类型:String、自定义类、接口、数组
- */
- public class Demo3 {
- //public void work(){}//()里无参数就是 无参
- public void work(String contect){}//()里有参数就是 有参
- public String work(){return “理想”;}//方法前不是void 说明是带返回值方法
- //public void work(){}//不带返回值的方法
- //调用实参 值传递
- /* public static void fun(int t){//定义 形参 t=a;
- System.out.println(“1t:”+t);//t=1
- t=2;
- System.out.println(“2t:”+t);//t=2
- }
- public static void main(String[] args) {
- int a=1;
- System.out.println(“1a:”+a); //a=1
- fun(a);//调用实参 值传递
- System.out.println(“2a:”+a);//不存在位置传递,自然a=1
- }*/
- //调用实参 引用传递
- /* public static void fun(int []t){//定义 形参 t[0]=a[0] a[0]堆地址给了变量t
- System.out.println(“1—t[0]:”+t[0]);//t[0]=1
- t[0]=2;
- System.out.println(“2—t[0]:”+t[0]);//t[0]=2 t[0]占用了原来a[0]的位置
- }
- public static void main(String[] args) {
- int []a=new int[]{1};
- System.out.println(“1—a[0]:”+a[0]);//a[0]=1
- fun(a);//调用实参 引用传递
- System.out.println(“2—a[0]:”+a[0]);//a[0]此时值=t[0]的值 2
- }*/
- //调用实参 值传递【注意传递的是a[0],也就是一个值】
- /* public static void fun(int t){//定义 形参
- t=2;
- }
- public static void main(String[] args) {
- int []a=new int[]{1};
- fun(a[0]);//调用实参 值传递
- System.out.println(a[0]);
- }*/
- }