目录
一、static成员
1.1 static修饰的成员变量
当我们定义一个类时,如果其中的某个成员变量不需要改变,我们可以用static来修饰它,称为静态成员变量,静态成员变量最大的特性是:不需要某个具体的对象,是所有对象所共享的。
例如:
class Student{
public String name;
public int age;
public static String classRoom = "计科211";
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Test {
public static void main(String[] args) {
Student student1 = new Student("zhangsan",10);
Student student2 = new Student("lisi",15);
System.out.println(Student.classRoom);
System.out.println(Student.classRoom);
}
}
我们也可以画图理解:
静态成员变量特性:
- 不属于某个具体的对象,是类的属性,所有对象共享。
- 可以通过对象访问,也可以通过类名访问,但最好是类名访问。
- 它的生命周期伴随类的一生。
- final定义的常量不能修改,final定义的静态常量不能修改且必须初始化。
1.2 static修饰成员方法
当static修饰成员方法时,就称为静态方法,也叫类方法。
例:
class Student{
public String name;
public int age;
public static String classRoom = "计科211";
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public static void Func(){
System.out.println("静态方法");
}
}
public class Test {
public static void main(String[] args) {
Student.Func();
}
}
注:
- 静态方法的调用不需要引用对象,直接使用类名调用,因此静态方法内不能直接访问非静态的变量或方法。
- 在静态方法中可以创建对象来间接访问非静态数据。
二、代码块
2.1 概念
使用 {} 定义的一段代码叫做代码块,可以分为一下几种:
- 普通代码块(本地代码块)
- 构造块(实例代码块)
- 静态块
- 同步代码块
2.2 普通代码块(本地代码块)
定义在方法内部的代码块,一般很少用到:
public static void Func(){
System.out.println("静态方法");
{
System.out.println("本地代码块");
}
}
2.3 构造块(实例代码块)
定义在类的内部,方法的外部。用来初始化实例成员变量,只有在创建对象时才会调用。
class Student{
public String name;
public int age;
public static String classRoom = "计科211";
{
this.name = "hh";
this.age = 10;
}
}
public class Test {
public static void main(String[] args) {
}
}
2.4 静态块
static修饰的代码块,一般用来初始化静态成员变量。
class Student{
public String name;
public int age;
public static String classRoom;
static{
classRoom = "计科211";
}
}
public class Test {
public static void main(String[] args) {
Student.Func();
}
当实例代码块、静态代码块、和构造方法同时出现时:
其先执行静态代码块,然后执行实例代码块,最后执行构造方法。
class Student{
public String name;
public int age;
public static String classRoom = "计科211";
public Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println("带有两个参数的构造方法");
}
public static void Func(){
System.out.println("静态方法!");
}
{
this.name = "haha";
System.out.println("实例代码块!");
}
static{
classRoom = "计科212";
System.out.println("静态代码块!");
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student("hehe",10);
}
}
当有两个静态方法时:
class Student{
public String name;
public int age;
public static String classRoom = "计科211";
public Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println("带有两个参数的构造方法");
}
public static void Func(){
System.out.println("静态方法!");
}
{
this.name = "haha";
System.out.println("实例代码块!");
}
static{
classRoom = "计科212";
System.out.println("静态代码块!");
}
}
public class Test {
public static void main(String[] args) {
System.out.println(Student.classRoom);
}
}
总结:
- 先执行静态的(加载了类就会被执行),且静态块只会执行一次。
- 如果有多个静态的,那么看定义顺序。
- 如果没有实例化对象,那么就只会执行静态的。
- 再执行实例化块,有多个实例化数据时就要看定义的顺序。
- 再执行构造方法。
三、内部类
- 一个类定义在另一个类或者方法的内部,前者称为内部类,后者称为外部类。
- 内部类也是封装的一种体现。
- 一个文件里面的不是内部类,只有一个类中的才是。
class OuterClass{
class InnerClass{
}
}
public class Test {
}
3.1 实例内部类
class OuterClass{
public int data1 = 1;
private int data2 = 2;
public static int data3 = 3;
class InnerClass{
public int data4 = 4;
private int data5 = 5;
public int data1 = 111;
public InnerClass() {
System.out.println("实例内部类的构造方法!");
}
public void innerFunc(){
System.out.println("实例内部类的普通方法!");
System.out.println(data1);
//访问与内部类同名的外部类的成员变量
System.out.println("外部类:"+ OuterClass.this.data1);
System.out.println(data2);
System.out.println(data3);
System.out.println(data4);
System.out.println(data5);
}
}
}
public class Test {
public static void main(String[] args) {
//OuterClass outerClass = new OuterClass();
//OuterClass.InnerClass innerClass = outerClass.new InnerClass();
//实例化内部类
OuterClass.InnerClass innerClass = new OuterClass().new InnerClass();
innerClass.innerFunc();
}
}
总结:
- 实例内部类不能定义静态的成员变量,如果要定义,就要加final修饰。
- 实例内部类中不能定义静态的成员方法。
- 如果在实例内部类内访问同名的外部类由static修饰的成员变量时,直接外部类类名.成员变量。
- 实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束。
- 会生成字节码文件: 外部类$内部类。
3.2 静态内部类
class OuterClass{
public int data1 = 1;
private int data2 = 2;
public static int data3 = 3;
static class InnerClass{
public int data4 = 4;
private int data5 = 5;
public static int data6 = 6;
private OuterClass outerClass;
public InnerClass(OuterClass outerClass){
System.out.println("静态内部类的构造方法!");
this.outerClass = outerClass;
}
public void func(){
System.out.println("func方法执行了!");
//访问非静态外部类成员变量
System.out.println(outerClass.data1);
System.out.println(outerClass.data2);
System.out.println(data3);
System.out.println(data4);
System.out.println(data5);
System.out.println(data6);
}
}
}
public class Test2 {
public static void main(String[] args) {
//实例化静态内部类
OuterClass.InnerClass innerClass = new OuterClass.InnerClass(new OuterClass());
innerClass.func();
}
}
注:
- 在静态内部类中只能访问外部类中的静态成员,不能在静态内部类中直接访问外部类的非静态的数据成员,可以通过实例化外部类对象来间接访问。
- 创建静态内部类对象时,不需要先创建外部类对象。
3.3 局部内部类
- 局部内部类定义在方法体内部,之饿呢过在该方法体内使用,其他位置不能使用。
- 不能被public、static等访问限定符修饰。
- 也有独立的字节码文件,命名格式:外部类名字$内部类名字。
public class Test2 {
public static void fun(){
class A{
public void test(){
System.out.println(1);
}
}
A a = new A();
a.test();
}
public static void main(String[] args) {
fun();
}
}
3.4 匿名内部类
class Person{
public String name;
public int age;
public void test(){
System.out.println("lisi");
}
}
public class Test2 {
public static void main(String[] args) {
//匿名对象,只能使用一次
new Person().test();
new Person(){
@Override
public void test() {
System.out.println("77777");
}
}.test();
}
}
四、对象的打印
class Person{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test3 {
public static void main(String[] args) {
Person person = new Person("zhangsan",10);
System.out.println(person);
}
}
当我重写ToString函数之后,编译器就会调用我重写的函数,可以实现对对象的打印,