面向对象具有三大特征:继承性、封装性、多态性
继承
//子类继承父类关键词extends
class 子类 extends 父类 {
}
优势
提高了代码的复用性
提高了代码的维护性
建立了类与类之间的关系,继承是多态的前提。
劣势
在一定程度上,造成类与类之间的强关联,即所谓的高耦合。
父类功能的改变对子类也会造成影响。
总结
父类有的,子类可以继承。
父类有的,子类可以去改变。
父类没有的,子类可以添加。
继承注意事项
父类的构造方法不能被继承。
构造方法不能被继承,但是可以通过super关键字去访问父类的构造方法。
方法和属性可以被继承。【只能去继承父类的非私有成员变量和成员方法】
super关键字必须是构造方法中的第一行语句。
子类的每一个构造方法的第一条语句默认都是super()。
java在创建一个子类对象的时候,首先去调用父类的不带参数的构造方法,生成父类对象,然后再去调用子类的构造方法,生成子类对象。
封装
封装的优点
1. 良好的封装能够减少耦合。
2. 类内部的结构可以自由修改。
3. 可以对成员变量进行更精确的控制。
4. 隐藏信息,实现细节。
实现Java封装的步骤
1. 修改属性的可见性来限制对属性的访问(一般限制为private),例如:
public class Person {
private String name;
private int age;
}
这段代码中,将 name 和 age 属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。
2. 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,例如:
public class Person{
private String name;
private int age;
?
public int getAge(){
return age;
}
?
public String getName(){
return name;
}
?
public void setAge(int age){
this.age = age;
}
?
public void setName(String name){
this.name = name;
}
}
采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。
以上实例中public方法是外部类访问该类成员变量的入口。
通常情况下,这些方法被称为getter和setter方法。
因此,任何要访问类中私有成员变量的类都要通过这些getter和setter方法。 注意!!! boolean类型的get()方法开头是is!!!
通过如下的例子说明EncapTest类的变量怎样被访问
/* F文件名 : RunEncap.java */
public class RunEncap{
public static void main(String args[]){
EncapTest encap = new EncapTest();
encap.setName("James");
encap.setAge(20);
encap.setIdNum("12343ms");
System.out.print("Name : " + encap.getName()+
" Age : "+ encap.getAge());
}
}
多态:
多态的优点
1. 消除类型之间的耦合关系
2. 可替换性
3. 可扩充性
4. 接口性
5. 灵活性
6. 简化性
多态存在的三个必要条件
继承
重写
父类引用指向子类对象
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。
以下是一个多态实例的演示,详细说明请看注释:
Test.java 文件代码:
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
执行以上程序,输出结果为:
吃鱼
抓老鼠
吃骨头
看家
吃鱼
抓老鼠
对象和类的概念
- 对象是具体的事物;类是对对象的抽象;
- 类可以看成一类对象的模板,对象可以看成该类的一个具体实例。
- 类是用于描述同一类型的对象的一个抽象概念,类中定义了这一类对象所应具有的共同的属性、方法
类的定义方式
// 每一个源文件必须有且只有一个public class,并且类名和文件名保持一致!
public class Car {
}
class Tyre { // 一个Java文件可以同时定义多个class
}
class Engine {
}
class Seat {
}
简单的学生类编写
public class Stu {
//属性:field(成员变量)
String name;
int age;
int id;
public static void main(String[] args) {
Stu stu= new Stu();
stu.name = "张三";
stu.age = 18;
stu.id = 1;
System.out.println("我叫"+stu.name+"。年龄:"+stu.age+"岁\t学号:"+stu.id);
}
Stu() {//构造方法
}
}
属性:field,或者叫成员变量
属性定义格式:
[修饰符] 属性类型 属性名 = [默认值] ;
方法
方法定义格式:
[修饰符] 方法返回值类型 方法名(形参列表) {
// n条语句
}
构造方法
[修饰符] 类名(形参列表){
//n条语句
}
要点:
1. 通过new关键字调用!!
2. 构造器虽然有返回值,但是不能定义返回值类型(返回值的类型肯定是本类),不能在构造器里使用return返回某个值。
3. 如果我们没有定义构造器,则编译器会自动定义一个无参的构造函数。如果已定义则编译器不会自动添加!
4. 构造器的方法名必须和类名一致!
public class TestConstructor {
public static void main(String[] args) {
Point p = new Point(3,4);
System.out.println(p.getSum());
}
}
class Point {
int n1, n2;
public Point(int _n1, int _n2) {
n1 = _n1;
n2 = _n2;
}
public int getSum() {
return n1+n2;
}
}
构造方法的重载
注意:
如果方法构造中形参名与属性名相同时,需要使用this关键字区分属性与形参。如示例4-6所示:
this.id 表示属性id;id表示形参id
this关键字
this最常的用法
1. 在程序中产生二义性之处,应使用this来指明当前对象;普通方法中,this总是指向调用该方法的对象。构造方法中,this总是指向正要初始化的对象。
2. 使用this关键字调用重载的构造方法,避免相同的初始化代码。但只能在构造方法中用,并且必须位于构造方法的第一句。
3. this不能用于static方法中。
public class TestThis {
int a,b,c;
public TestThis() {
super();
}
public TestThis(int a, int b) {
// super();
// TestThis();这样是无法调用方法
this();//调用无参的方法,且必须为第一行
//这样就区分了成员变量,这种情况占了this使用情况大多数
this.a = a;
this.b = b;
System.out.println("带两个参数的构造器:a="+a+" b="+b);
}
public TestThis(int a, int b, int c) {
// super();
this(a,b);
this.a = a;
this.b = b;
this.c = c;
System.out.println("带三个参数的构造器:a="+a+" b="+b+" c="+c);
}
void sing( ) {
System.out.println("sing被调用了");
}
void eat() {
this.sing();
System.out.println("shit");
System.out.println();
}
public static void main(String[] args) {
TestThis t1 = new TestThis(2,3,4);
t1.eat();
}
}
static关键字
核心要点:static修饰的成员变量和方法,从属于类。普通变量和方法从属于对象的。
package
注意事项:
1. 写项目时都要加包,不要使用默认包。
2. com.gao和com.gao.car,这两个包没有包含关系,是两个完全独立的包。只是逻辑上看起来后者是前者的一部分。
导入类import
1. Java会默认导入java.lang包下所有的类,因此这些类我们可以直接使用。
2. 如果导入两个同名的类,只能用包名+类名来显示调用相关类:
java.util.Date date = new java.util.Date();
静态导入
//以下两种静态导入的方式二选一即可
import static java.lang.Math.*;//导入Math类的所有静态属性
import static java.lang.Math.PI;//导入Math类的PI属性
public class Test2{
public static void main(String [] args){
System.out.println(PI);
System.out.println(random());
}
}