目录
代码块:
内部类:
前言:
在现实生活中,我们每一个个体都是作为对象而存在的,而我们需要用代码将这些复杂的对象描绘出来,那么就需要我们站在编程的思想上去理解。在用类实例化对象时,有一些成员属性或者成员变量我们是不希望被外界直接访问的,但同时会提供一些公共的接口,来支持对它们的一些操作。
在Java中主要通过类和访问权限修饰符来体现出封装的特性,类可以将数据以及封装数据的方法结合在一起,访问权限用来控制方法或者字段能否直接在类外使用。
访问权限:
public
🎈同一包中同一类或者不同类,不同包中的子类或者非子类都可以访问。
private
🎈只能在本类内进行访问。
protected
🎈同一包中同一类,或者不同类,不同包中的子类可以访问。
默认权限
🎈什么修饰符都不写,又称为包访问权限,同一包中同一类或者不同类可以访问。
示例:(一般成员属性用private修饰,成员变量用public修饰)
class Person{
private int age;
private String name;
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class Test1 {
public static void main(String[] args) {
Person stu = new Person();
stu.setAge(21);
stu.setName("aaaa");
System.out.println(stu.getName() + stu.getAge());
}
}
可以清楚的看见类中对私有成员提供了一些方法来设置和获取它。
Person stu = new Person();
😯这句代码就是用Person类来实例化stu这个对象,stu是局部变量存储在栈区,new是在堆区申请的一块空间,stu存储这块空间的地址,指向这块空间。可以看见Person后有一对括号,这个实际上是调用了构造成员方法,调用构造成员方法是实例化对象的必要条件,它是支持重载的。后面详细讲解。
static成员:
在Java中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的。
static修饰成员变量
class W{ static int a = 10; } public class Test2 { public static void main(String[] args) { W p1 = new W(); System.out.println(W.a); System.out.println(p1.a); } }
🐵被static修饰的成员变量不属于某一个对象,它属于整个类,是所有对象共享的。所以可以通过类名去访问静态成员变量,虽然也可以通过对象去访问,但一般都是用类名去访问的。
🐵它的生命周期随类的加载就形成了,类的卸载而销毁。
🐵它存储在JVM中的方法区。
注意:局部变量是不可以被static修饰的。
static修饰成员方法
class W{ private int a; private static int b; public void fun2(){ System.out.println("aaaa"); } public static void fun(){ b = 20; W p1 = new W(); p1.a = 10; p1.fun2(); } } public class Test2 { public static void main(String[] args) { W p1 = new W(); W.fun(); p1.fun(); } }
🪖与static修饰成员变量的作用区域一致,也是属于整个类,不属于某一个对象。
🪖可以对象引用的方法去调用,但一般用类名去调用。
🪖在static修饰的成员方法内,只能直接访问静态成员属性。
🪖由于非静态成员属性是属于某一个类的,和静态成员方法相比,本质上是不同的,所以需要对象的引用方法去访问。
🪖静态方法中不可以直接调用非静态成员方法,由于非静态成员方法中存在对象的引用this参数,而静态成员方法属于整个类,不存在this。只有通过对象引用的方法去调用。
static成员变量初始化
注意:静态成员变量初始化一般不通过构造方法来完成,构造方法中初始化的是与对象相关的实例属性。
就地初始化
public class Test3 { private static int a = 10; }
🎄定义时直接在后面赋初值,由于它属于整个类,用这个类实例化出的对象访问的都是同一个a。
🎄静态代码块也可以初始化静态成员变量。
代码块
普通代码块
public class Test3 { private int a; public void fun(){ int b = 10; { int c = 10; } } }
💎定义在方法内部,c就是一般的局部变量,作用域也就在这个括号的区域里。
构造代码块
public class Test3 { private int a; { a = 20; } }
🧢定义在类中的代码块(不加任何修饰符),一般用于初始化成员变量。只有在实例化对象时才会执行。
静态代码块
class W1{ public static int a; private int b; static { a = 20; System.out.println("aaa"); } } public class Test3 { public static void main(String[] args) { W1.a = 50; } }
😉它不属于某一个对象,是类的属性,因此是在JVM加载类时开辟空间并初始化的。不管有多少个对象,就仅仅执行类加载这一次,如果有多个静态代码块,会按顺序执行。
这里还有同步代码块,后续会进行详解。
内部类
实例内部类
未被ststic修饰的内部类
class OutClass{ static int a; public int b; int c; public void fun(){ System.out.println("aaa"); } public static void fun3(){ System.out.println("aaaa"); } class InterClass{ int c; int a2; public int b2; private int c2; public void fun2(){ a = 10; b = 20; c = 30; //内部类c System.out.println(c); //外部类c OutClass.this.c = 500; System.out.println(OutClass.this.c); fun(); fun3(); } } } public class Test4 { public static void main(String[] args) { //分别实例化外部类对象和内部类对象 OutClass s = new OutClass(); OutClass.InterClass s2 = s.new InterClass(); s2.fun2(); } }
🎈内部类可以直接访问外部类任何修饰符,修饰的成员变量。
🎈如果内部类和外部类有相同的成员变量,在内部类成员方法中优先访问内部类中的成员变量(就近原则),想要访问外部类中相同的成员变量需要声明OutClass.this.c = 500;
🎈要访问实例内部类中成员,必须要实例化内部类的对象,而普通内部类定义与外部类成员定义位置相同,因此创建实例内部类对象时必须借助外部类。
OutClass s = new OutClass();
OutClass.InterClass s2 = s.new InterClass();🎈实例内部类中非静态成员方法中包含指向外部类对象的引用this。
🎈外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。
静态内部类
被ststic修饰的内部类
class OutClass1{ int a; private int b; static int c; public static void fun(){ System.out.println("aaaaa"); } static class InterClass1{ int a2; private int b2; static int c2; public void fun2(){ c = 20; fun(); } } } public class Test5 { public static void main(String[] args) { OutClass1.InterClass1 s = new OutClass1.InterClass1(); s.fun2(); } }
🐵静态内部类是不依赖于对象的,和静态成员变量有相似之处,它只能访问外部类中的静态成员变量和方法,要想访问非静态成员变量或者方法,就得创建对象。
🐵静态内部类创建对象是不依赖于外部类对象的,因此直接就可以创建内部类对象。
OutClass1.InterClass1 s = new OutClass1.InterClass1();
局部内部类
class OutClass1 { int a; private int b; static int c; public static void fun5() { class InterClass1 { int a2; private int b2; public void fun2() { System.out.println("aab"); } } InterClass1 s1 = new InterClass1(); s1.fun2(); } } public class Test5 { public static void main(String[] args) { OutClass1 s1 = new OutClass1(); s1.fun5(); } }
🧢故名思意就是创建在局部中的类,那么它只能在局部使用,局限性很大,且不能被public等访问修饰符修饰,一般使用很少。
匿名内部类后续进行详解
续:构造成员方法
class Person2{ int age; String name; public Person2(){ System.out.println("aaa"); } public Person2(int age, String name){ this.age = age; this.name = name; } } public class Test6 { public static void main(String[] args) { Person2 stu = new Person2(); Person2 stu2 = new Person2(21,"wu"); System.out.println(stu2.name + stu2.age); } }
🎉构造成员方法是用类实例化对象的一个必要条件,当我们自己没有写构造方法时,编译器会自己提供无参的构造方法,但我们一旦写了构造成员方法,编译器则不提供。
🎉构造成员方法名是和类名相同的,并且没有返回值。
🎉构造成员方法支持重载。
小结:
🐵面向对象编程思想的学习,需要我们深入的去理解,去思考,大量动手实践,相信会有不一样的收获。