- 名词解释
- 成员变量
- 实例变量:其实就是对象
- 静态变量:属于类,存在方法区
- package:
- 避免类的命名冲突,同包类中的类不能同名
- 类的全称:包名.类命
- 包名常常有层次结构cm.csdn.oop
- 建议:包名所有字母都小写
- import:
- 同包中的类可以直接访问
- 不同包中的类不能直接访问,若访问需要用import引用
- 访问控制修饰符:数据(成员变量)私有化,行为(方法)公开化(我有嘴巴,有耳朵,这是我的私有的,但是我会唱歌,会跳舞,会跑步,这是我的行为公开的)
- public:公开的,任何类
- protected:受保护的,本类、派生类、同包类
- default(默认)不写:什么也不写,本类,同包类(同包类可以继承,夸包就不可以了),
- private:私有的,本类
- private修饰的静态方法和静态变量,只能在本类中使用;
- private修饰的方法和属性是私有的,只能在本类中使用,不能被继承。
- 说明:
- 类的访问权限只能是public或默认的,夸包的情况下,只有public可以被继承,一个类只能有一个public 可以有多个默认的
- 类中成员的访问权限如上四种都可以
- 属性的可见性有四种:公有的(public)、保护的(protected)、默认的(default)、私有的(private)
- 就是当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。java内存模型在变量修改后将新的变量值同步回主内存,在其他线程读取该变量之前从主内存刷新变量值来实现可见性。
- 对于顶层类(外部类)来说,只有两种修饰符:public和默认(default)。 因为外部类的上一单元是包,所以外部类只有两个作用域:同包,任何位置。 因此,只需要两种控制权限:包控制权限和公开访问权限,也就对应两种控制修饰符:public和默认(default)。 但是private可以修饰class的,只不过该类不能是顶层类,可以是内部类 内部类的上一级是外部类,那么对应的有四种访问控制修饰符:本类(private),同包(default),父子类(protected),任何位置(public)。 当一个内部类使用了private修饰后,只能在该类的外部类内部使用
- 方法中定义的是局部变量,不能用类成员变量修饰符 private。
public class Something {
private String s="";
void doSomething () {
//private String s = ""; //此处编译错误错误
int l = s.length();
}
}
(单选题)下列哪种说法是正确的(D )
A.本类中实例方法可以调用其他类中所有实例方法
B.本类中实例方法可以调用其他类中类方法
C.本类中实例方法可以直接通过方法名调用其他类的实例方法
D.本类中实例方法可以直接通过方法名调用本类中其他实例方法
A. 本类实例方法不可以调用其他类的私有实例方法。
B. 本类实例方法不可以调用其他类的私有类方法。
C.本类实例方法不可以直接通过方法名调用其他类的实例方法。
class Loo{ //演示静态变量
int a; //实例变量
static int b; //静态变量
int i;
Loo(){
a++;
b++;
}
void show(){
System.out.println("a="+a+",b="+b);
}
void temp(){
show();
}
- final:最终的、不可改变的
- 修饰变量:变量不能被改变
- 修饰方法:方法不能被重写
- 修饰类:类不能被继承
- final方法为最终方法,不可修改,即子类不可以覆盖父类的final方法
- final变量 为常量 一旦声明,就不可修改
- final类为最终类,不可以扩展,即不可以被继承
- 子类可以继承父类的中非私有的方法、变量,构造方法也不可以
- 注意:如下两个案例:final修饰引用类型,是引用不能改变,而引用指向的内容是可以改变的。
public static void main(String args[]){
final Student stu1 = new Student("Tom",25);
Student stu2 = new Student("Jerry",23);
//stu1 = stu2;编译错误,stu1是final修饰的,引用不能改变
stu2 = stu1; //stu2没有被file修饰,所以地址可以改变
stu1.setName("Jerry"); //引用指向的对象是可以改变的
stu1.setAge(25); //引用指向的对象是可以改变的
}
//此代码段就是final修饰引用类型,引用不能改变,但是内容是可以改变的
public class Something {
public static void main(String[] args) {
Other o = new Other();
new Something().addOne(o);
}
public void addOne(final Other o) {
o.i++;
}
}
class Other {
public int i;
}
//错误示例:此代码段就是final修饰变量的,变量不能被改变
public class Something {
public int addOne(final int x) {
//return ++x; 编译错误, final 修饰为常量,常量的值不能被改变。
return 0;
}
}
- static:
- 静态的,类在编译的时候生成java.class字节码文件,存在于方法区;
- 静态在加载运行的时候 只会执行一次,不会再被初始化了
- 类的实例方法存在一个专门的区叫方法区,事实上类刚加载的时候就被加载好了,不过它们在"睡眠"状态,这些方法必须当有对象产生的时候才会"苏醒"
- 静态的东西存在静态区,他们和类是一个等级的,就是说只要类被加载,它们就可以直接用(用类名来调用)
- 类方法、变量可以通过类命.来调用;(也可以通过对象来调用,不过我们不推荐用对象调用)
- 注意:普通方法可以直接调用静态变量
- 静态块是类加载的时候就会被执行到的,静态执行顺序是按照在类中出现 的先后顺序执行。 静态变量-静态块-静态方法-构造方法
public class Images {
//构造方法
private Images(){
}
//静态变量
public static BufferedImage start;
//静态块
static {
start = getImage("start.png");
}
//静态方法
public static BufferedImage getImage(String path){
try {
ImageIO.read(FlyingObject.class.getResource(path));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
- 这里引入了一个静态构造方法,什么是静态构造方法?如下:
public class Test1 {
public static void main(String[] args) {
Doctor = null;
/**
* 声明对象,不会报错
* 实例化对象,调用了私有化的构造方法,程序报错
* 如下:
* s = new Doctor();//错误,无法实例化对象
*/
}
}
//String 构造
class Doctor{
private Doctor(){
//将构造方法进行了封装私有化,那么此构造方法只能在本类中可见!
}
}
//因为Doctor类中的构造方法被私有化了,
//只能在本类Doctor中可见,
//不能再外部直接实例化!只能在Doctor 内部使用!
//而我们创建对象其实就是new 构造方法
所以封装,不仅体现在类的封装、属性的封装、也有方法的封装、那就包括构造方法
构造方法可以被封装为任意四种类型
public class Test2 {
public static void main(String[] args) {
//声明对象,不会报错
Teacher s = null;
}
}
class Teacher{
//在内部产生本类的实例化对象
Teacher teacher = new Teacher();
private Teacher(){
//将构造方法进行了封装私有化,此构造方法只能在本类中可见!
}
}
- 静态方法只能调用静态的东西,即使new对象,对象向的属性也得是静态的
- 普通方法可以调用非静态的
public static void main(String[] args) {
getInstance();
}
public static void getInstance(){
Teacher teacher = new Teacher();
}
static class Teacher{
//在内部产生本类的实例化对象
Teacher teacher = new Teacher();
private Teacher(){
//将构造方法进行了封装私有化,此构造方法只能在本类中可见!
}
}
private Test(){}
private static Test test;
public static Test getInstance(){
return test = new Test();
}
- 静态变量:
- 由static修饰
- 静态成员只会初始化一次
- 属于类,存在方法区中,只有一份
- 常常通过类命点来访问
- 何时用:所有对象所共享的数据(图片、音频、视频等)
- 静态方法:
- 由static修饰
- 属于类,存在方法区中,只有一份
- 常常通过类命点来访问
- 静态方法中没有隐士this传递,在静态方法中不能直接访问实例成员。静态方法中只能访问静态变量 有个默认类.静态变量,不写有默认
class StaticStuff{
static int x=10;
static{
x+=5;
}
public static void main(String args[]){
//静态方法访问其他实例需要new 对象,用对象的引用去访问
System.out.println("x=" + x); //同一个类中,静态访问静态,类命不写有默认,
||
System.out.println("x=" + StaticStuff.x);
}
static {
x/=3;
}
}
- 在类方法中可以通过实例化对象调用实例方法。
- 何时用:方法的操作与对象无关
- 静态块:static{ }
- 由static修饰
- 属于类,在类被加载时自动执行,一个类只被加载一次,所以静态块也只执行一次
- 何时用:初始化/加载静态资源(图片、音频、视频等)
- 案例:
//static的演示
public class StaticDemo {
public static void main(String[] args) {
//加载Noo.class到方法区中,同时系统会自动执行静态块,静态只执行一次
Noo o4 = new Noo();
Noo o5 = new Noo();
Noo o6 = new Noo();
//静态块
//构造方法
//构造方法
//构造方法
}
}
class Noo{ //演示静态块
static {
System.out.println("静态块");
}
Noo(){
System.out.println("构造方法");
}
}
class Loo{ //演示静态变量
int a; //实例变量
static int b; //静态变量
Loo(){
a++;
b++;
}
void show(){
System.out.println("a="+a+",b="+b);
}
//静态成员存在方法区,因为类只会被加载一次,所以静态也只会被初始化一次
public static void main(String[] args) {
Loo a = new Loo();
a.show();//1,1
Loo b = new Loo();
a.show();//1,2
Loo c = new Loo();
a.show();//1,3
}
class Moo{ //演示静态方法
int a; //实例变量(对象点来访问)
static int b; //静态变量(类名点来访问)
void show(){ //有this传递
System.out.println(this.a);
System.out.println(Moo.b);
}
static void test(){
/**
* 静态方法中没有隐式this传递,没有this就意味着没有对象
* 而实例变量a必须通过对象来访问
* 所以如下代码发生编译错误:
* System.out.println(a); //编译错误
*/
System.out.println(Moo.b);
}
}
- 内存图:类.class文件先被加载到方法区,1、方法区(类.class字节码文件、静态),2、堆(对象、实例),3、栈(变量、方法参数)
![](https://img-blog.csdnimg.cn/20210312232837174.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zNjU4MDkzMA==,size_16,color_FFFFFF,t_70)
- 注意:静态方法
- 可以被继承和隐藏
- 不能够被重写
- 不能实现多态
- 不能实现父类的引用可以指向不同子类的对象进行多态调用。
- 如果调用的是静态方法,类型是谁,调用的就是谁的
class Super {
public static void m1() {
System.out.println("m1 in Super");
}
public void m2() {
System.out.println("m2 in Super");
}
}
class Sub extends Super {
public static void m1() {
System.out.println("m1 in Sub");
}
public void m2() {
System.out.println("m2 in Sub");
}
}
public class TestMain {
public static void main(String args[]) {
Super sup = new Sub();
sup.m1();
sup.m2();
Sub sub = (Sub) sup;
sub.m1();
sub.m2(); }
}
m1 in Super
m2 in Sub
m1 in Sub
m2 in Sub