目录
4.4 作用于修饰符
4.4.2 非访问修饰符
1. static修饰符
static修饰符用来修饰类的成员变量和成员方法,也可以形成静态代码块。被static修饰的成员变量和成员方法一般成为静态变量和静态方法,可以直接通过类名访问它们。语法格式为:
类名.静态方法名(参数列表);
类名.静态变量名;
- 静态变量:static修饰的成员变量独立于该类的任何对象,被所有类共享。无论一个类实例化多少对象,它的静态变量都只有一份。局部变量不能被声明为static变量。
- 静态方法:static用来修饰独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据。static方法必须被实现。静态方法可以通过类名调用它,任何对象都可以调用,因此静态方法中不能使用this和super关键字,不能访问所属类的成员变量和成员方法,只能访问所属类的静态变量和静态方法。
- static和final:static和final修饰的成员变量一但初始化,他的值就不可修改,并且通过类名访问,建议用大写字母命名。用static和final修饰的成员方法不可被重写,通过类名访问。例:
public class StaticTest { public static final String BANANA = "香蕉"; public static float price = 5.2f; static{ System.out.println("static静态块"); } public static void test() { System.out.println(StaticTest.BANANA + "的价格是: " + StaticTest.price); } public static void main(String[] args) { StaticTest st = new StaticTest(); st.test(); System.out.println("main()中, "+st.BANANA+"的price =" + st.price); } }
2. final修饰符
final可以修饰类,方法,变量,意义不同,但本质相同,都是表示不可改变。
- final修饰类中的变量:final修饰的成员变量表示常量,值一旦确定就无法改变。final可以修饰成员变量、局部变量、静态变量。final变量定义时,可以先声明,而不赋予值,这种变量被称为final空白。
- final修饰类中的方法:如果一个类不允许其子类覆盖某个方法,则可以将这个方法声明为final方法。格式如下:
[修饰符] final 返回值类型 方法名([参数类型 参数, ……]){ 方法体 }
- final修饰类:final声明的类不能被继承。如果一个类不需要子类,且细节不需要改变,则这个类可以声明为final。格式为:
final class 类名 { 类体 }
实例:final关键字的使用
public class Father { final int f = 9; final void work() { System.out.println("我在上班..."); } } public class Son extends Father{ public static void main(String[] args) { Son s = new Son(); s.f = 12; System.out.println(s.f); void work() { } } }
输入上述代码将会提示错误,原因为子类无法为父类的final变量和final方法重新分配值和重写方法。
3.abstract修饰符
abstract用来修饰类,被修饰的类称它为抽象类。抽象类不能用来实例化为对象,声明抽象类的目的是为了将来对该类进行扩充。
抽象类可以包含非抽象方法和抽象方法。如果一个类包含若干个抽象方法,该类必须被声明为抽象类。抽象类可以不包含抽象方法。
抽象方法不能被声明为static和final。任何继承抽象类的子类必须实现抽象类的方法。
4.5 封装
实例:
public class Person {
private String name;//修饰符 数据类型 变量名;
private int age;//修饰符 数据类型 变量名;
private float weight;//修饰符 数据类型 变量名;
public String getName(){
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
//验证类的属性
if (age <= 0 || age > 150){
System.out.println("年龄不能为负值,设为默认18岁");
this.age = 18;
}
else {
this.age = age;
}
}
public float getWeight(){
return weight;
}
public void setWeight(float weight){
//验证类的属性
if (weight <= 0 || weight >= 1000){
System.out.println("体重不能为负值,设为默认50公斤");
this.weight = 50;
}
else {
this.weight = weight;
}
}
}
public class Test {
public static void main(String[] args) {
Person p1 = new Person();
p1.setName("张三");
p1.setAge(18);
p1.setWeight(80);
System.out.println(p1.getName());
System.out.println(p1.getAge());
System.out.println(p1.getWeight());
}
}
本例中,name、age、weight被设置为private,张泽阳其他类就无法访问。封装就是把一个对象私有化,同时提供一些方法供外界访问属性。本例中Test类通过public方法访问Person类的属性。封装在不影响使用的情况下保护了数据。
4.6 继承
实例:
public class Animal {
public String name;
private int id;
public void eat(){
System.out.println(name + "正在吃");
}
public void sleep(){
System.out.println(name + "正在睡");
}
}
public class Cat extends Animal{
public void shout(){
System.out.println(name + "正在叫");
}
}
该例中,子类虽然只有一个方法shout( ),但它继承了父类的一个变量和两个方法。private属性不能被继承。
1.子类继承父类的成员变量:
- 子类能够继承父类的public和protected成员变量,不能继承private成员变量。
- 如果子类和父类在同一个包,则可以继承,否则不能。
- 如果继承父类的子类中有和父类同名的成员变量,则子类会屏蔽父类的成员变量;如果子类想要访问父类的同名变量,需要使用super关键字。
2.子类继承父类的方法:
-
子类能够继承父类的public和protected方法,不能继承private方法。
-
如果子类和父类在同一个包,则可以继承,否则不能。
-
如果继承父类的子类中有和父类同名的成员方法,则子类会屏蔽父类的成员方法;如果子类想要访问父类的同名方法,需要使用super关键字。
3. 构造方法
子类不能继承父类的构造方法。如果父类的构造方法都是带参数的,则必须在子类的构造方法中显式地通过super关键字调用父类的构造方法并配置参数列表。如果父类有无参构造方法,则在子类中地构造方法中调用父类的构造方法不是必须使用super关键字,如果没有用super关键字,系统会自动调用父类的无参构造方法。
实例:
public class Circle extends Shape {
private double radius;
public Circle(){
// super("Circle");
radius = 0;
}
public Circle(double radius){
// super("Circle");
this.radius = radius;
}
public Circle(String name, double radius){
// super(name);由于父类没有无参构造方法,所以子类的构造方法必须用super方法调用父类的有参构造方法。
this.name = name;
this.radius = radius;
}
}
public class Shape {
protected String name;
public Shape(){
name = "shape";
}
public Shape(String name){
this.name = name;
}
}
4.7 重载
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。最常用的地方就是构造器的重载。实例:
public class Test {
void Test(){
System.out.println("No parameters");
}
void Test(int a){
System.out.println("a:" + a);
}
void Test(int a, int b){
System.out.println("a and b:" + a + " " + b);
}
double Test(double a){
System.out.println("double a:" + a);
return a * a;
}
public static void main(String[] args) {
Test d1 =new Test();
d1.Test();
d1.Test(2);
d1.Test(2, 3);
d1.Test(2.0);
}
}
方法的重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。
注意:
- 方法名称必须相同
- 方法的参数列表(参数类型、参数个数、参数顺序)至少有一项不同,仅仅参数变量名称不同是不可以的
- 方法的返回值类型和修饰符不做要求
4.8 多态
4.7继承其实就是多态的一种表现,调用一系列具有相同名称的方法,根据不同参数得到不同结果,它属于静态多态。这种多态是在代码编译阶段就确定下来的。动态多态在程序运行阶段才能体现出来。
接下来讲述几个和多态相关的概念:
- 向上转型:父类对象通过子类对象实例化
- 向下转型:父类对象可以转换为子类对象,但必须强制转换
- 多态存在要有三个前提:
- 要有继承关系
- 子类要重写父类方法
- 父类引用指向子类
实例:
public class Animal {
int age = 10;
public void eat(){
System.out.println("动物吃东西");
}
public void shout(){
System.out.println("动物在叫");
}
public static void run(){
System.out.println("动物在跑");
}
}
public class Dog extends Animal {
String name = "黑子";
public void eat() {
System.out.println("狗在吃东西");
}
public static void run(){
System.out.println("狗在奔跑");
}
public void watchDoor(){
System.out.println("狗在看门");
}
}
public class Test {
public static void main(String[] args) {
Animal a1 = new Dog();//向上转型
// Dog d1 = Dog a1;//向下转型
a1.eat();
a1.shout();
a1.run();
// a1.watchDoor();指向子类的父类引用不能调用子类存在而父类不存在的方法
System.out.println(a1.age);
// System.out.println(d1.name);
}
}
要点:
- dog类继承了animal类
- 子类重写了eat()和run()方法
- 父类数据类型的引用指向子类对象 Animal a1 = new Dog()
- 指向子类的父类引用只能访问父类中拥有的方法和属性
- 对于子类中存在而父类中不存在的方法,该引用是不能使用的
- 若子类重写了父类中的某些方法,调用它们时,必须是使用子类中定义的这些方法
- 父类对象a1向下转型为子类dog,就可以访问子类独有的方法了
定义和导入包
包的作用 1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
2、如同文件夹一样,包也采用了树形目录的存储方式。
3、包也限制了访问权限,拥有包访问权限的类才能访问某个包中的类
语法格式 :
package 包名1[包名2[包名3…]]
导入包:
import package1[.package2...].(classname|*)