Java是面向对象的程序设计语言,Java语言提供了定义类、成员变量、方法等最基本的功能
类和对象
类是面向对象的重要内容,可以把类当成一种自定义类型,可以使用类来定义变量,这种类型的变量
统称为引用变量,也就是说,所有类都是引用类型
定义类
[修饰符] class 类名 {
零个或多个构造器定义
零个或多个成员变量
零个或多个成员方法
}
定义成员变量
[修饰符] 类型 成员变量名 [=默认值];
定义方法
[修饰符] 方法返回值类型 方法名(形参列表) {
// 方法体
}
构造器
[修饰符] 构造器(形参列表) {
// 由零条到多条可执行的语句组成构造器的执行体
}
public class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void say() {
System.out.println("name: " + name + " ,age: " + age);
}
public static void main(String[] args) {
Person person = new Person("Tom", 18);
person.say();
}
}
name: Tom ,age: 18
Process finished with exit code 0
注意:一般来说,如果调用static修饰的成员时省略了前面的主调,那么默认使用该类作为主调;
如果调用没有static修饰的成员时省略了前面的主调,那么默认使用this作为主调
成员变量和局部变量
成员变量是在类里定义的变量
局部变量是在方法里定义的变量
封装
封装指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问
为了良好的封装,需要从两个方面考虑
- 将对象的成员变量和实现细节隐藏起来,不允许外部直接访问
- 把方法暴露出来,让方法来控制对这些成员变量进行安全的访问和操作
private:当前类访问权限
default:包访问权限
protected:子类访问权限
public:公共访问权限
如果一个Java类的每一个实例变量都被使用private修饰,并为每个实例提供了public修饰的setter和getter方法,那么这个类就是一个符合JavaBean规范的类
继承
Java继承具有单继承的特点,每个子类只有一个直接父类
修饰符 class SubClass extends SuperClass {
// 类定义部分
}
package day3;
public class Fruit {
public double weight;
public Fruit(double weight) {
this.weight = weight;
}
public Fruit() {
}
public void info() {
System.out.println("水果:" + weight + "g");
}
}
package day3;
public class Apple extends Fruit{
public static void main(String[] args) {
Apple apple = new Apple();
apple.weight = 56;
apple.info();
}
}
水果:56.0g
Process finished with exit code 0
如果定义一个Java类时并未显式指定这个类的直接父类,则这个类默认继承自java.lang.Object类
package day3;
class Parent {
public String tag = "parent";
}
class Derived extends Parent {
private String tag = "child";
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
}
public class HideTest {
public static void main(String[] args) {
Derived d = new Derived();
d.setTag("derived");
System.out.println(((Parent)d).tag); // 访问父类的tag变量
System.out.println(d.getTag());
}
}
parent
derived
Process finished with exit code 0
为了在子类方法中访问父类中定义的,被隐藏的实例变量,或为了在子类中调用父类中定义的、被覆盖的方法,可以通过super作为限定来调用这些实例变量和实例方法
package day3;
class Creature {
public Creature() {
System.out.println("Creature的无参构造器");
}
}
class Animal extends Creature {
public Animal(String name) {
System.out.println("Animal 带一个参数的构造器," + "该动物的name:" + name);
}
public Animal(String name, int age) {
this(name);
System.out.println("Animal 带两个参数的构造器," + "该动物的age:" + age);
}
}
public class Wolf extends Animal {
public Wolf() {
super("大灰狼", 10);
System.out.println("Wolf的无参构造器");
}
public static void main(String[] args) {
new Wolf();
}
}
Creature的无参构造器
Animal 带一个参数的构造器,该动物的name:大灰狼
Animal 带两个参数的构造器,该动物的age:10
Wolf的无参构造器
从上面这个例子来看,创建任何对象总是从该类所在继承树最顶层类的构造器开始执行,然后依次向下执行,最后才执行本类的构造器
多态
子类其实是一种特殊的父类,因此Java允许把一个子类对象直接赋值给一个父类引用变量,无须任何类型转换,或者被称为向上转型,向上转型由系统自动完成
相同类型的变量、调用同一个方法时呈现出多种不同的行为特征,这就是多态
package day3;
class BaseClass {
public int number = 6;
public void base() {
System.out.println("父类的普通方法");
}
public void test() {
System.out.println("父类被覆盖的方法");
}
}
public class SubClass extends BaseClass {
public int number = 10; // 覆盖父类的number实例变量
public void test() {
System.out.println("子类覆盖父类的方法");
}
public void sub() {
System.out.println("子类的普通方法");
}
public static void main(String[] args) {
BaseClass bc = new BaseClass();
System.out.println(bc.number);
bc.base();
bc.test();
System.out.println("---------");
SubClass sc = new SubClass();
System.out.println(sc.number);
sc.base();
sc.test();
sc.sub();
System.out.println("---------");
BaseClass polymorphicBc = new SubClass();
System.out.println(polymorphicBc.number);
polymorphicBc.base();
polymorphicBc.test();
((SubClass)polymorphicBc).sub();
System.out.println(((SubClass)polymorphicBc).number);
System.out.println("---------");
}
}
6
父类的普通方法
父类被覆盖的方法
---------
10
父类的普通方法
子类覆盖父类的方法
子类的普通方法
---------
6
父类的普通方法
子类覆盖父类的方法
子类的普通方法
10
---------
Process finished with exit code 0
Java引用变量有两个类型:一个是编译时类型,一个是运行时的类型
编译时的类型由声明变量时使用的类型决定
运行时类型由实际赋给该变量的对象决定
引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法