一. static关键字
static可以用来修饰:属性、方法、代码块、内部类。
(1)static修饰属性:静态变量(类变量)
属性按是否使用static修饰可以分为:静态属性和非静态属性(实例变量)。
实例变量:当创建了类的多个对象时,每个对象独立的拥有一套类中的非静态属性,当修改其中一个对象的非静态属性时,不会导致其他对象中同样的属性被修改。
静态变量:当创建了类的多个对象时,多个对象共享同一个静态变量,当修改其中一个对象的静态变量时,其他对象的静态变量也被修改。
public class Test{
public static void main(String[] args) {
Chinese person1 = new Chinese();
person1.name = "张";
person1.country = "China";
Chinese person2 = new Chinese();
person2.name = "王";
person2.country = "CHINA";
System.out.println(person1.name); //张
System.out.println(person1.country); //CHINA
}
}
class Chinese{
String name;
int age;
static String country;
}
静态变量随着类的加载而加载,要早于对象的创建,可以通过 " 类 . 静态变量 " 的方式调用。由于类只加载一次,则静态变量在内存中也只会存在一份(在方法区的静态域中)。
public class Test{
public static void main(String[] args) {
Chinese.country = "中国";
// Chinese.name = "刘"; 错误:只能调用静态变量
Chinese person1 = new Chinese();
System.out.println(person1.country); //中国
Chinese person2 = new Chinese();
System.out.println(person2.country); //中国
}
}
class Chinese{
String name;
int age;
static String country;
}
(2)static修饰方法:静态方法
静态方法随着类的加载而加载,可以通过 " 类 . 静态方法 " 调用。
在静态方法中,只能调用静态的方法或属性,在非静态方法中,既可以调用静态方法,也可以调用非静态方法。
在静态方法中,不可以使用this和super。
public class Test{
public static void main(String[] args) {
Chinese.nation();
}
}
class Chinese{
String name;
int age;
static String country;
public void show(){
System.out.println("自我介绍");
//调用非静态结构
introduction(); //this.introduction();
System.out.println(name); //System.out.println(this.name);
//调用静态结构
nation();
System.out.println(country); //System.out.println(Chinese.country);
}
public static void nation(){
System.out.println("中国人");
//调用静态结构
hometown();
System.out.println(Chinese.country);
//不能调用非静态结构
//introduction();
//System.out.println(name);
}
public void introduction(){
System.out.println("姓名:" + name + ", 年龄:" + age);
}
public static void hometown(){
System.out.println("北京");
}
}
属性可以被多个对象所共享,不会随着对象的不同而不同,这样的属性可以声明为statiic;
操作静态属性的方法,通常声明为static。
二. 代码块
代码块的作用:初始化类和对象。
只能用static来修饰代码块,因此代码块可以分为静态代码块和非静态代码块。
静态代码块:(1)内部可以有输出语句;(2)随着类的加载而执行,且只执行一次;(3)作用:初始化类的信息;(4)如果一个类中定义了多个静态代码块,则按声明的顺序执行;(5)静态代码块内只能调用静态的属性和方法,不能调用非静态的属性和方法。
非静态代码块:(1)内部可以有输出语句;(2)随着对象的创建而执行,每创建一次就执行一次代码块;(3)作用:可以在创建对象时,对对象的属性等进行初始化;(4)如果一个类中定义了多个非静态代码块,则按声明的顺序执行;(5)即可以调用静态的属性和方法,也可以调用非静态的属性和方法。
public class PersonTest {
public static void main(String[] args){
// 静态代码块随着类的加载而执行
String base = Person.base; //输出: hello static
// 我是一个人
//非静态代码块随着对象的创建而执行
Person person1 = new Person(); //输出: hello static
// 我是一个人
// 姓名:null, 年龄:0
System.out.println(person1.country); //中国
}
}
class Person{
//属性
String name;
int age;
String country;
static String base = "人";
//构造器
public Person(){
}
public Person(String name, int age){
this.name = name;
this.age = age;
}
//代码块
//(1)静态代码块
static {
System.out.println("hello static");
//可以调用静态属性和静态方法
base = "我是人";
basic();
//不可以调用非静态属性和方法
//country = "中国";
//introduction();
}
//(2)非静态代码块
{
System.out.println("hello");
//可以调用静态属性和静态方法
base = "我是人";
basic();
//可以调用非静态属性和方法
country = "中国";
introduction();
}
//方法
public void introduction(){
System.out.println("姓名:" + name + ", 年龄:" + age);
}
public static void basic(){
System.out.println("我是一个人");
}
}
三. final关键字
final可以用来修饰:类、方法、变量
final修饰类:该类不能被继承,如String类、System类
final修饰方法:该方法不能被重写
final修饰变量:该变量为常量,final修饰属性时可以赋值的位置有:显示初始化、代码块内初始化、构造器内初始化
public class PersonTest {
public static void main(String[] args){
}
}
final class Creature{ //该类不能被继承
}
//class Person extends Creature{
//}
class Person{
String name;
//显示初始化
final int AGE = 22; //该属性为常量,不能修改,必须为其赋值(赋值方式有:显示初始化、代码块内初始化、构造器内初始化)
//AGE ++;
final int height;
//代码块内初始化
{
height = 180;
}
final int weight;
//构造器内初始化
public Person(){
weight = 120;
}
public final void introduction(){ //该方法不能被重写
System.out.println("姓名:" + name + ", 年龄:" + AGE);
}
}
class Man extends Person{
// public void introduction(){ 不能重写
// System.out.println("姓名:" + super.name + ", 年龄:" + super.age + "性别:" + this.sex);
// }
}
四. abstract(抽象类)
abstract可以用来修饰:类、方法
abstract修饰类:(1)抽象类不能实例化(不能创造该类的对象);(2)抽象类中可以没有抽象方法;(3)一般都会提供抽象类的子类,通过实例化子类来调用抽象类中的结构
abstarct修饰方法:(1)抽象方法只有方法的声明,没有方法体;(2)包含抽象方法的类一定是抽象类;(3)若子类重写了父类的所有抽象方法,则可以实例化子类,如果子类没有重写父类的所有抽象方法,则需要将子类声明为抽象类。
public class PersonTest {
public static void main(String[] args){
//Person person = new Person(); 不能创造该类的对象
Man man = new Man();
man.introduction();
}
}
abstract class Person{ //抽象类
String name;
int age;
public Person(){
}
public Person(String name, int age){
this.name = name;
this.age = age;
}
public void introduction(){
System.out.println("姓名:" + name + ", 年龄:" + age);
}
abstract public void eat(); //抽象方法
}
class Man extends Person {
char sex = '男';
public void eat(){ //需要对父类的抽象方法进行重写
System.out.println("吃饭");
}
}
五. interface(接口)
(1)接口和类是两个并列的结构,在接口内只能定义全局常量(public static final)、抽象方法(public abstact)、静态方法、默认方法;
(2)接口中不能定义构造器,因此接口不可以实例化(给接口创建对象);
(3)接口通过类实现(implements)的方式来使用,如果实现类实现了接口中所有的方法,则此实现类可以实例化。
public class Test{
public static void main(String[] args) {
Boy boy = new Boy();
boy.eat();
}
}
interface Man{
//全局常量
public static final int age = 18;
char sex = '男'; //在接口中定义的属性默认为全局常量,省略了public static final
//抽象方法
public abstract void eat();
void sleep(); //在接口中定义的方法默认为抽象方法,省略了public abstract
}
class Boy implements Man{
//实现接口中的所有方法
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
(4)一个类可以实现多个接口(该类需要实现所有接口中的所有方法)
class A extends B implements C,D :类A继承了类B,实现了接口C和D
public class Test{
public static void main(String[] args) {
}
}
class B{
}
interface C{
}
interface D{
}
class A extends B implements C,D{
}
(5)一个接口可以继承其他接口,且可以多继承
public class Test{
public static void main(String[] args) {
}
}
interface A{
}
interface B{
}
interface C extends A,B{
}
(6)接口满足多态性
public class Test{
public static void main(String[] args) {
Person person = new Person();
Boy boy = new Boy();
person.show(boy); //吃饭
}
}
class Person{
public void show(Man man){ //Man man = new Boy();
man.eat();
}
}
interface Man{
char sex = '男';
void eat();
void sleep();
}
class Boy implements Man{
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
(7)接口中可以定义静态方法、默认方法
public class Test{
public static void main(String[] args) {
Man man = new Man();
//接口中定义的静态方法只能通过接口来调用
//man.eat(); 错误
Person.eat(); //吃饭
//通过实现类的对象来调用接口中的默认方法
man.sleep(); //睡觉
//如果实现类重写了接口中的默认方法,则调用的是重写后的方法
man.walk(); //走路
//如果子类(实现类)的父类和实现的接口中声明了同名同参的默认方法,并且如果子类没有对方法进行重写,则默认调用父类中的方法
//如果实现类实现了多个接口,而这多个接口中声明了同名同参的默认方法,并且如果实现类没有对方法进行重写,则会报错;如果想要调用此方法,则必须重写
man.live(); //生命
}
}
interface Person{
//静态方法
public static void eat(){
System.out.println("吃饭");
}
//默认方法
public default void sleep(){
System.out.println("睡觉");
}
public default void walk(){
System.out.println("走");
}
public default void live(){
System.out.println("活着");
}
}
class Creature{
public void live(){
System.out.println("生命");
}
}
class Man extends Creature implements Person{
public void walk(){
System.out.println("走路");
}
//在子类(实现类)中调用父类或接口中被重写的方法
public void show(){
walk(); //调用自己
super.live(); //调用父类
//调用接口
Person.super.live();
Person.super.walk();
}
}
六. 内部类
将类A声明在类B中,则类A称为内部类,类B称为外部类。
内部类分为:成员内部类(静态、非静态)和 局部内部类(方法内、代码块内、构造器内)
成员内部类:(1)类内可以定义属性、方法、构造器等;(2)可以被继承;(3)可以被abstract修饰;(4)可以调用外部类的结构;(5)可以被权限修饰符修饰
public class PersonTest {
public static void main(String[] args){
Animal.Dog dog = new Animal.Dog(); //创建静态成员内部类的实列
dog.showDog();
Animal animal = new Animal();
Animal.Cat cat = animal.new Cat(); //创建非静态成员内部类的实列
cat.eatCat();
}
}
class Animal{
String name;
int age;
public void eat(){
System.out.println("吃饭");
}
static class Dog{
int age;
public void showDog(){
System.out.println(age);
}
}
class Cat{
String name;
public void showCat(){
System.out.println(name);
}
public void eatCat(){
Animal.this.eat(); //内部类内可以调用外部类的方法
}
public void showName(String name){
System.out.println(name); //形参
System.out.println(this.name); //Cat内的
System.out.println(Animal.this.name); //Animal内的
}
}
public void show(){
//局部内部类
class A{
}
}
}