一、static关键字
- 静态(static)可以修饰属性和方法。
- 称为静态属性(类属性)、静态方法(类方法)。
- 静态成员是全类所有对象共享的成员。
- 在全类中只有一份,不因创建多个对象而产生多份。
- 不必创建对象,可直接通过类名访问。
示例:
public class Person {
private String name;
private int age;
static String city;//静态属性
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void test() {
System.out.println("test().......");
}
public static void staticMethod() {
//静态方法
System.out.println("city:" + city);
}
}
静态属性
静态属性,不属于对象。
非静态属性(实例属性)属于对象,随着对象的创建而产生,每个对象的属性值都是独立的。
静态属性是属于类的,只有一份(节省内存)。应该由类来访问,但是对象也可以访问,所有的对象共享着一份数据。
非静态属性由对象访问:对象.属性–>赋值,取值
静态属性由类访问:类名.静态属性–>赋值,取值
静态属性可以和final搭配使用,形成静态常量。
static final double PI = 3.14;//静态常量
静态方法
静态方法,属于类而不再属于对象了,应该由类来访问,但是对象也可以访问。
普通的方法由对象调用。
静态方法中:只能访问属于类,不能访问属于对象。
A:访问静态属性
B:访问静态方法
C:不能直接访问非静态属性
D:不能直接访问非静态方法
非静态方法中:属于类,属于对象都可以访问
A:访问静态属性
B:访问静态方法
C:访问非静态属性
D:访问非静态方法
示例:
public class Person {
private String name;
private int age;
static String city;//静态属性
static final double PI = 3.14;//静态常量
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void test() {
System.out.println("test().......");
}
public void print() {
//访问静态属性、非静态属性
System.out.println("name:" + name + ";" + "age:" + age + ";city:" + city);
//访问静态方法、非静态方法
staticDemo();
test();
}
public static void staticDemo() {
System.out.println("staticDemo()......");
}
//静态方法
public static void staticMethod() {
//访问静态属性
System.out.println("city:" + city);
//访问静态方法
staticDemo();
//不能直接访问非静态属性
// System.out.println("name:"+name);
// System.out.println("age:"+age);
//不能直接访问非静态方法
// print();
}
}
静态代码块
代码块,就是一块代码。使用{}包裹起来的。
示例:
public class Demo2 {
String name;
int age;
static {
System.out.println("这是静态代码块......");
}
{
System.out.println("这是构造代码块......");
}
public Demo2() {
System.out.println("这是无参构造函数......");
}
public Demo2(String name, int age) {
System.out.println("这是有参构造函数......");
this.name = name;
this.age = age;
}
public static void main(String[] args) {
{
System.out.println("这是普通代码块......");
int k = 10;
System.out.println(k);
}
Demo2 demo2 = new Demo2();
}
}
- 普通代码块:{}包裹起来一段代码。注意作用域。
- 构造代码块:写在类里,方法外的代码块,就叫构造代码块。当创建对象的时候,随着构造函数的调用而执行。而且优先于构造函数执行。构造函数被多次调用,那么构造代码块也被多次调用。
- 静态代码块:用static关键字修饰的代码块。在类第一次使用的时候执行,优先于main的执行。只执行一次。例如连接数据库的驱动等。
- 同步代码块:多线程。
优先级别:静态代码块 > 构造代码块 >构造方法
二、继承
概念
生活中我们经常听到一些名词,譬如富二代,官二代等,它代表着人与人之间的一种关系。那么程序当中怎么表示这种关系呢?
概念:
描述两个类的关系的。在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类(派生类,SubClass),现有类被称作父类(超类,SuperClass),子类会自动拥有父类所有非私有的属性和方法。
意义:
A:避免重复的代码。(从子类的角度)
B:扩展类的功能。(从父类的角度)
继承性:
子类对象,可以直接访问父类的非私有的属性和方法。(避免重复代码)
子类可以新增自己的属性和方法。(扩展类的功能)
子类可以重新实现父类已有的方法。(扩展类的功能)
语法
语法结构:
class 父类 {
}
class 子类 extends 父类 {
}
extends关键字:表示两个类是继承关系。
示例:
//父类
public class Animal {
private String type;
int age;
String color;
public Animal() {
System.out.println("父类Animal无参构造函数......");
}
public Animal(String type, int age, String color) {
System.out.println("父类Animal有参构造函数......");
this.type = type;
this.age = age;
this.color = color;
}
public void eat() {
System.out.println("动物吃东西.....");
}
public void print() {
System.out.println("type:" + type + ";age:" + age + ";color:" + color);
}
}
//子类
public class Cat extends Animal {
//新增属性
String name;
public Cat() {
System.out.println("子类Cat无参构造......");
}
public Cat(String type, int age, String color, String name) {
super(type, age, color);//super()指代父类构造函数的时候,也只能放在第一句,如果显式调用了某个构造函数,就不会默认调用无参构造了
System.out.println("子类Cat有参构造函数......");
this.name = name;
}
//重新实现父类的方法
@Override//相当于加了约束,
public void eat(){
System.out.println("猫吃鱼........");
}
//新增方法
public void catchMouse() {
System.out.println("抓老鼠......");
}
}
super关键字
子类对象的创建过程:
子类的构造方法中,默认先调用父类的无参构造方法。如果没有显式的调用,那么隐含着super()。
super关键字:
可以访问父类的属性;
可以访问父类的方法;
指代父类的构造方法, 如果有多个,靠参数来区分。
要在第一行。
this关键字:
作为本类的对象,访问本类的属性,如果在继承中,本类没有这个属性,那么再找父类中;
访问本类的方法;
可以指代本类的构造方法:this()。
要在第一行。
示例:
//父类
public class A {
int i;
int j;
public A() {
}
public A(int i, int j) {
this.i = i;
this.j = j;
}
public void testA() {
System.out.println("i:" + i);
System.out.println("j:" + j);
}
public void fun() {
System.out.println("父类的fun方法....");
}
}
//子类
public class B extends A {
int i;//和父类有相同的属性
public B() {
}
public B(int i, int j, int i1) {
super(i, j);//用super指代父类构造方法
this.i = i1;//用this访问本类属性
}
public void testB() {
System.out.println("i:" + super.i);//用super访问父类属性
System.out.println("j:" + j);
super.fun();//用super访问父类方法
this.fun();//用this访问本类方法
}
public void fun() {
System.out.println("子类的fun方法....");
}
}
this和super的对比:
No. | 比较点 | this | super |
---|---|---|---|
1 | 访问属性 | 首先在子类中查找,如果没有就在分类中查找 | 直接在父类中查找 |
2 | 访问方法 | 首先在子类中查找,如果没有就在父类中查找 | 直接访问父类中的方法 |
3 | 调用构造 | 调用本类中的其它构造方法 | 调用父类的构造方法 |
4 | 特殊 | 只自身的引用 | 没有概念 |
this,super关键字不能出现在static方法中。
方法重写【重点】
概念:继承关系中,子类将父类已有的方法重新实现,叫做方法重写。
关键字:override
示例:
public class Person {
String name;
public void eat() {
System.out.println("Person类eat()方法.....");
}
public Person getType() {
System.out.println("Person类的getType()方法.....");
return null;
}
}
public class Man extends Person {
//将父类已经有的方法重新实现
@Override
public void eat() {
System.out.println("Man类eat()方法.....");
}
@Override//约束我们一定要符合重写的规则
public Man getType() {
System.out.println("Man类的getType()方法.....");
return null;
}
}
规则:
A:继承关系中。
B:子类重写的方法的声明,必须和父类一致。方法的返回值(注意点:子类重写的方法的返回类型可以是父类方法返回类型的子类),参数列表,方法名。
C:子类重写方法的访问权限,不能比父类更加严格。
D:重写的方法,不能抛出比父类更大的异常。
方法重载:
概念:一个方法,因为参数不同,执行的具体的方法也不同。
关键字:overload
规则:
A:同一个类中。
B:方法名必须一致。
C:参数列表必须不同:顺序,个数,类型。
方法重写和方法重载的对比:
No. | 比较点 | 方法重写 | 方法重载 |
---|---|---|---|
1 | 单词 | Overrid | Overload |
2 | 范围 | 继承(子类) | 同一个类里 |
3 | 对方法的要求 | 和父类的方法名一致,参数列表一致,返回类型一致 | 方法名一致,参数列表不同,返回值类型无要求 |
4 | 对访问权限的要求 | 不能比父类的访问权限更加严格 | 对访问权限无要求 |
三、访问修饰符
访问权限:对类,方法,变量,常量等访问位置的限定,通过访问修饰符来实现。
在Java中,可以在类、类的属性以及类的方法前面加上一个修饰符(modifier),来对类进行一些访问上的控制。
private:私有的,限制在本类中才能访问。
default:什么都不写,就是default。同类,同包。
protected:受保护的,同类,同包,不同包(限于子类访问)
public:公共的,同类,同包,不同包。
示例:
package com.idiot.part3;
public class Test {
private int age;//private 只能在本类中访问
int i;//default:什么都不写,就是default。同类,同包。
protected int j;//protected:受保护的,同类,同包,不同包(限于子类访问)
public void print() {//public:公共的,同类,同包,不同包。
System.out.println("age:" + age);
}
}
package com.idiot.part3;
/*
* 同一个包,不同类
*/
public class TestDemo {
public static void main(String[] args) {
Test t = new Test();
//System.out.println("age:" + t.age);private 修饰,同一个包,不同的类,不能访问
System.out.println("i:" + t.i);//default 修饰,同一个包,不同的类,可以访问
System.out.println("j:" + t.j);//protected 修饰,同一个包,不同的类,可以访问
t.print();//public 修饰,同一个包,不同的类,可以访问
}
}
package com.idiot.part3.other;
import com.idiot.part3.Test;
/*
* 在不同的包,不同的类,是子类
*/
public class SubTest extends Test {
public void func() {
System.out.println("j:" + j);//protected:受保护的,同类,同包,不同包(限于子类访问)
}
}
package com.idiot.part3.other;
import com.idiot.part3.Test;
/*
* 不同的类,不同的包
*/
public class TestDemo2 {
public static void main(String[] args) {
Test t = new Test();
//System.out.println("i:" + t.i);//default 修饰,不同包,不同的类,不能访问
//System.out.println("j:" + t.j);//protected 修饰,不同包,不同的类,不能访问(限于子类访问)
t.print();//public 修饰,不同包,不同的类,,可以访问
}
}
对类的修饰:只能是default和public,protected不能修饰一个类。
四个访问修饰符的对比:
修饰符 | 同一个类中 | 同一个包中 | 子类中(不同包) | 全局 |
---|---|---|---|---|
private | Yes | |||
* | Yes | Yes | ||
protected | Yes | Yes | Yes | |
public | Yes | Yes | Yes | Yes |
private <
default< protected < public
四、final关键字
词意:终结的,最终的,最后的。
final可修饰的内容:
类(最终类)
方法(最终方法)
变量(最终变量)
final修饰类:此类不能被继承。String、Math、System均为final修饰的类,不能被继承。
final修饰方法:此方法不能被覆盖。意为最终方法,不支持子类以覆盖的形式修改。
final修饰变量:此变量值不能被改变(常量)。所有final修饰的变量只能赋值一次,值不允许改变。
final修饰基本类型:值不可变
final修饰引用类型:地址不可变
静态常量不再提供默认值,必须手动赋予初始值。
示例:
public final class Animal {
private String name;
//静态的常量
public static final double PI = 3.14;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public final void eat() {
System.out.println("动物吃东西......");
}
}
//public class Dog extends Animal{//final修饰的类不能被继承
//
// //final修饰的方法不能被重写
// public void eat(){
//
// }
//}
public class TestAnimal {
public static void main(String[] args) {
final int age = 23;//常量:final修饰基本类型:值不可变
System.out.println("age:" + age);
// age = 34;//值不可变
// System.out.println("age:" + age);
final Animal a = new Animal();//final修饰引用类型:地址不可变
a.setName("woowow");
//a = new Animal();//地址不可变
a.setName("12121212");
}
}