Java基础学习(三)
1.类变量(静态变量)和类方法(静态方法)static
- 类变量是所有类对象共享的,类变量可以通过类名.类变量和对象名.类变量来访问,但通常使用类名.类变量
类变量是在类加载时就创建了,所以我们没有创建对象实例时,也可以通过类名来访问类变量 - 静态方法类似于静态变量,开发自己的工具类时,通常使用静态方法,方便使用。静态方法中不能使用this 和super。只能访问静态变量和静态方法。
package com.static_;
public class TestStatic {
public static void main(String[] args) {
Student curry = new Student("Curry");
curry.count++;
Student tom = new Student("Tom");
tom.count++;
Student car = new Student("Car");
car.count++;
System.out.println(curry.count); //3
System.out.println(tom.count); //3
System.out.println(car.count); //3
System.out.println(Student.count); //3
}
}
class Student{
private String name;
public static int count;
public Student(String name) {
this.name = name;
}
}
2.代码块
2.1普通代码块
- 代码块属于初始化块,属于类中的成员,类似与方法,将逻辑语句封装在方法体中。
- 把相同的语句,放在一个代码块里,不管调用哪个构造器,创建对象,都会优先调用代码块内容
- 代码块调用的顺序优先于构造器
- 当创建一个子类对象,父类的构造器也被调用,所以父类中的代码块也会被调用。
package com.codeblock_;
public class CodeBlock01 {
public static void main(String[] args) {
Movie movie = new Movie("蜘蛛侠");
//结果:
// 电影屏幕打开
// 广告开始
// 电影屏幕打开
// 播放蜘蛛侠
Movie movie1 = new Movie("唐探3", 20, "陈");
//结果
// 电影屏幕打开
// 广告开始
// 电影屏幕打开
// 播放唐探3
}
}
//把相同的语句,放在一个代码块里,不管调用哪个构造器,创建对象,都会优先调用代码块内容
//代码块调用的顺序优先于构造器
class Movie {
{
System.out.println("电影屏幕打开");
System.out.println("广告开始");
System.out.println("电影屏幕打开");
}
private String name;
private double price;
private String director;
public Movie(String name) {
this.name = name;
System.out.println("播放"+ name);
}
public Movie(String name, double price) {
this.name = name;
this.price = price;
System.out.println("播放"+ name);
}
public Movie(String name, double price, String director) {
this.name = name;
this.price = price;
this.director = director;
System.out.println("播放"+ name);
}
}
2.2静态代码块
- static代码块也叫静态代码块,作用就是对类初始化,而且随着类的加载而执行,并且只会执行一次,如果是普通代码块,每创建一个对象就执行。
- 调用类的静态成员,静态代码块会被调用。
- 调用子类的静态成员,父类的静态代码块也会被调用。
- 使用类的静态成员,普通代码块不会被调用。
package com.codeblock_;
public class CodeBlock02 {
public static void main(String[] args) {
AA aa = new AA();
/*输出:
BB的静态代码块1被执行
AA的静态代码块1被执行
*/
System.out.println(Cat.n1);
/*输出:
Animal的静态代码块1被执行
Cat的静态代码块1被执行
30
*/
}
}
class Animal {
static {
System.out.println("Animal的静态代码块1被执行");
}
}
class Cat extends Animal{
public static int n1 = 30;
static {
System.out.println("Cat的静态代码块1被执行");
}
}
class BB {
static {
System.out.println("BB的静态代码块1被执行");
}
}
class AA extends BB{
static {
System.out.println("AA的静态代码块1被执行");
}
}
-创建一个对象时,调用的顺序为
1.调用静态代码块和静态属性初始化。(优先级一样,按定义的顺序调用)。
2.调用普通代码块和普通属性初始化。(优先级一样,按定义的顺序调用。)
3. 构造器。
package com.codeblock_;
public class CodeBlock03 {
public static void main(String[] args) {
A a = new A();
// 结果:
// getN1被调用
// A 的静态代码块被调用
// A的普通代码块被调用%$
// getN2被调用
}
}
class A{
{
System.out.println("A的普通代码块被调用");
}
private int n2 = getN2();
private static int n1 = getN1();
static {
System.out.println("A 的静态代码块被调用");
}
public static int getN1() {
System.out.println("getN1被调用");
return 100;
}
public int getN2() {
System.out.println("getN2被调用");
return 100;
}
}
2.3 创建一个对象时调用顺序的总结
父类静态代码和静态属性初始化->子类静态代码和静态属性初始化->父类普通代码块和普通属性初始化->父类构造方法->子类的普通代码块和普通属性初始化->子类的构造方法。
3.final关键字
- 被final修饰的类不能被其他类继承
- 被final修饰的方法不能被子类重写,可以被继承
- 被final修饰的属性不能被修改
- final修饰的属性可以在定义时、代码块、构造器中赋值。
- 被static修饰的final属性只能在定义和静态代码块中赋值
- final和static搭配使用,不会导致类加载
package com.codeblock_;
public class CodeBlock04 {
public static void main(String[] args) {
System.out.println(Demo.i); //16
}
}
class Demo {
public static final int i = 16;
static {
System.out.println("demo被加载");
}
}
4.abstract
- 当类的方法没有实现,只有定义时,用abstract修饰该方法,这个方法是抽象方法,同时要用abstract修饰该类,该类为抽象类。
abstract class Animal{
String name;
int age;
abstract public void cry();
}
- 抽象类不能被实例化
- 如果一个类继承了抽象类,必须实现抽象类的所有抽象方法,否则也要定义为抽象类。
5.接口
结构
interface InterfaceName{
//属性
//方法(抽象方法,默认实现方法,静态方法)
void function();
default void function1(){};
static void function2() {};
}
- 普通类使用接口必须实现接口中的所有方法
- 接口不能被实例化
- 抽象类实现接口可以不实现接口中所有方法
- 一个类可以实现多个接口
- 接口中的方法默认为public abstract
- 接口中的属性默认为public static final
- 接口和接口之间是继承关系
6.内部类
- 内部类可以直接访问外部类私有属性
- 分类
定义在类局部位置上(比如方法内)
1 局部内部类(有类名)
2 匿名内部类(没有类名)
定义在类的成员位置上
1 成员内部类 (没用static修饰)
2 静态内部类 (使用static修饰)
6.1 局部内部类
- 可以直接访问外部类的所有成员,包含私有的
- 不可以添加访问修饰符,因为他的地位就是一个局部变量,但可以使用final
- 作用域:仅仅在定义它的方法或代码块中
- 访问外部类中的成员:直接访问
- 外部类在方法中,可以创建内部类对象,然后调用内部类成员
- 外部其他类,不能访问内部类
- 如果外部类与局本内部类的成员重名,遵循就近原则,如果想访问外部类成员,使用外部类名.this.成员
package com.innerclass;
public class LocalInnerClass {
public static void main(String[] args) {
Outer r = new Outer();
r.m1();
}
}
class Outer{
private int n1 = 100;
private void m2() {
System.out.println("m2被调用");
}
public void m1() {
//不可以添加访问修饰符,因为他的地位就是一个局部变量,但可以使用final
//作用域:仅仅在定义它的方法或代码块中
//外部类在方法中,可以创建内部类对象,然后调用内部类成员
final class Inner{
private int n1 = 800;
public void f1(){
System.out.println("Inner 的 n1 =" + n1);
System.out.println("Outer 的 n1 =" + Outer.this.n1);//可以直接访问外部类的所有成员,包含私有的
m2(); //访问外部类中的成员:直接访问
}
}
new Inner().f1();
}
}
6.2 匿名内部类
- 相当于继承了类或实现了接口
package com.innerclass;
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer01 outer01 = new Outer01();
outer01.method();
}
}
class Outer01 {
private int n1 = 10;
public void method() {
//基于接口的匿名内部类
//类只使用一次,以后不再使用
//tiger 的编译类型 A
//tiger 的运行类型 匿名内部类
A tiger = new A() {
@Override
public void cry() {
System.out.println("老虎叫。。。。");
}
};
Father father = new Father("jack"){
@Override
public void test() {
System.out.println("匿名内部类的test");
}
};
tiger.cry();
father.test();
}
}
interface A {
public void cry();
}
class Father {
public Father (String name){
}
public void test() {}
}
6.3 成员内部类
- 可以访问外部类的所有成员
- 可以添加访问修饰符
package com.innerclass;
public class MemberInnerClass {
public static void main(String[] args) {
Outer02 outer02 = new Outer02();
outer02.t1();
Outer02.Inner02 inner02 = outer02.new Inner02(); //创建内部类对象
inner02.say();
}
}
class Outer02 {
private int n1 = 10;
public String name = "张三";
class Inner02 {
public void say() {
System.out.println("n1 = " + n1 + " name = " + name);
}
}
public void t1() {
Inner02 inner02 = new Inner02();
inner02.say();
}
}
6.4 静态内部类
- 只能访问外部类的静态成员,不能访问非静态成员。
- 可以添加访问修饰符
- 可以直接通过外部类名访问
package com.innerclass;
public class StaticInnerClass {
public static void main(String[] args) {
//两种创建内部类的方法
Outer03.Inner03 inner03 = new Outer03.Inner03();
inner03.say();
Outer03.Inner03 inner031 = Outer03.Inner03.getInstance();
inner031.say();
}
}
class Outer03 {
private int n1 = 10;
private static String name = "jack";
static class Inner03 {
//只能访问外部类的静态成员,不能访问非静态成员。
//可以添加访问修饰符
public void say() {
System.out.println(name);
}
public static Inner03 getInstance() {
return new Inner03();
}
}
}