Java面向对象03

1,package和import:

  • package:声明包

    • 作用:避免类名的冲突
    • 同包中的类不能同名,不同包中的类可以同名
    • 类的全称:包名.类名,包名常常有层次结构
    • 建议:包名所有字母都小写
  • import:导入类(写在package下)

    • 同包中的类可以直接访问,不同包中的类不能直接访问,若想访问:

      • 先import导入类,再访问类-----------建议
      • 类的全称------------------------------------太繁琐、不建议

2, 访问控制修饰符:----------------------作用:保护数据的安全

  • public:公开的,任何类

  • private:私有的,本类

  • protected:受保护的,本类、派生类、同包类

  • 默认的:什么也不写,本类、同包类-------------------------java不建议默认权限

注意:

  1. 类的访问权限只能是public或默认的
  2. 类中成员的访问权限如上4种都可以
  3. 访问权限由高到低依次为:public>protected>默认的>private
package ooday05;
//访问控制修饰符的演示
public class Aoo {
    public int a;    //任何类
    protected int b; //本类、派生类、同包类
    int c;           //本类、同包类
    private int d;   //本类

    void show(){
        a = 1;
        b = 2;
        c = 3;
        d = 4;
    }
}

class Boo{ //演示private
    void show(){
        Aoo o = new Aoo();
        o.a = 1;
        o.b = 2;
        o.c = 3;
        //o.d = 4; //编译错误
    }
}

package ooday05_vis;
import ooday05.Aoo;
public class Coo { //演示同包的
    void show(){
        Aoo o = new Aoo();
        o.a = 1;
        //o.b = 2; //编译错误
        //o.c = 3; //编译错误
        //o.d = 4; //编译错误
    }
}

class Doo extends Aoo{ //跨包继承----演示protected
    void show(){
        a = 1;
        b = 2;
        //c = 3; //编译错误
        //d = 4; //编译错误
    }
}

 3,final:最终的、不能改变的------------单独应用几率低

修饰变量:变量不能被改变

//演示final修饰变量
class Eoo{
    final int a = 5;
    void test(){
        //a = 55; //编译错误,final的变量不能被改变
    }
}

修饰方法:方法不能被重写

//演示final修饰方法
class Foo{
    final void show(){}
}
class Goo extends Foo{
    //void show(){} //编译错误,final的方法不能被重写
}

修饰类:类不能被继承

//演示final修饰类
final class Hoo{}
//class Ioo extends Hoo{} //编译错误,final的类不能被继承
class Joo{}
final class Koo extends Joo{} //正确,不能当老爸,但能当儿子

 4,static:静态的

静态变量:

  • 由static修饰

  • 属于类,存储在方法区中,只有一份

  • 常常通过类名点来访问(也可以用对象名来引用,但是不推荐)

  • 何时用:所有对象所共享的数据(图片、音频、视频等)

class Loo{ //演示静态变量
    int a;
    static int b;
    Loo(){
        a++;
        b++;
    }
    void show(){
        System.out.println("a="+a+",b="+b);
    }
}

public class StaticDemo {
    public static void main(String[] args) {
        Loo o1 = new Loo();
        o1.show();
        Loo o2 = new Loo();
        o2.show();
        Loo o3 = new Loo();
        o3.show();
        System.out.println(Loo.b); //常常通过类名点来访问
    }
}

过程: 首先加载类,将类中的静态变量和所有方法放到方法区中,并同时运行静态块。

            然后加载loo对象(这时实例变量和静态变量都已经赋默认值),然后调用构造方法。

            然后将变量放到栈中,并指向堆中的对象。

            最后调用方法区中的show方法给a,b赋值。

 静态方法:

  • 由static修饰

  • 属于类,存储在方法区中,只有一份

  • 常常通过类名点来访问(也可以用对象名来引用,但是不推荐)

  • 静态方法中没有隐式this传递,所以不能直接访问实例成员

  • 何时用:方法的操作与对象无关

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传递,没有this就意味着没有对象
        //而实例变量a必须通过对象点来访问,所以如下语句编译错误
        //System.out.println(a); //编译错误
        System.out.println(Moo.b);
    }
}

class Noo{ //演示静态方法何时用
    int a; //实例变量(描述对象的属性)

    //show方法中访问了对象的属性a,意味着与对象有关,所此不能设计为静态方法
    void show(){
        System.out.println(a);
    }
    //plus方法中没有访问对象的属性,意味着与对象无关,所以建议设计为静态方法
    static int plus(int num1,int num2){
        int num = num1+num2;
        return num;
    }
}

public class StaticDemo {
    public static void main(String[] args) {
        Moo.test(); //常常通过类名点来访问
    }
}

 静态块:

  • 由static修饰

  • 属于类,在类被加载期间自动执行,一个类只能加载一次,所以静态块也只执行一次

  • 何时用:加载/初始化静态资源(图片、音频、视频等)

class Poo{
    static { //加载类时自动执行----最早执行
        System.out.println("静态块");
    }
    Poo(){
        System.out.println("构造方法");
    }
}

public class StaticDemo {
    public static void main(String[] args) {
        Poo o4 = new Poo();
        Poo o5 = new Poo();
        Poo o6 = new Poo();
    }
}

 用构造方法赋值和用静态块赋值的不同:

 

 

 补充:

1,成员变量分两种:

  • 实例变量:没有static修饰,属于对象的,存储在堆中,有几个对象就有几份,通过引用/对象打点来访问
  • 静态变量:由static修饰,属于类的,存储在方法区中,只有一份,能过类名打点来访问

2, 内存管理:由JVM来管理的

  • 堆:new出来的对象(包括实例变量)
  • 栈:局部变量(包括方法参数)
  • 方法区:.class字节码文件(包括静态变量、所有方法)

 3,

Scanner scan = new Scanner(System.in);
int a = scan.nextInt();       //实例方法
double b = scan.nextDouble(); //实例方法

double c = Math.random(); //静态方法
Arrays.sort(arr);         //静态方法

1.常见问题:
  1)图片必须放在与src并列关系的img文件夹中,否则读取不到
  2)测试的时候一定要保证输出的都是8,因为明天要往窗口上画了
  3)如下代码是重载了还是重写了?
    class Aoo{
      void show(){
      }
    }
    class Boo extends Aoo{    //Boo把Aoo中的show()继承过来了
      void show(String name){ //在此处发生了重载
      }
    }

    Boo o = new Boo();
    o.show();
    o.show("zhangsan");

2.常见面试题:
  1)重写与重载的区别:
    1.1)重写(override):发生在父子类中,方法名相同,参数列表相同
        ----当觉得从超类继承过来的方法不好时,所做的修改
    1.2)重载(overload):发生在同一类中,方法名相同,参数列表不同
        ----是完全不同的方法,只是方法名正好相同而已
  2)实例变量与静态变量的区别:
    2.1)实例变量:
          没有static修饰,属于对象,存储在堆中,有几个对象就有几份,由对象点来访问
    2.2)静态变量:
          由static修饰,属于类,存储在方法区中,只有一份,由类名点来访问
3.代码分析题:-----------Aoo o = new Boo();
    //静态块是在加载类的时候自动执行,构造方法是在创建对象时自动执行
    //静态块一定先执行超类的,而后再执行派生类的
    //构造方法一定先执行超类的,而后再执行派生类的
    //输出: 1,3,2,4
    class Aoo{
      static{
        System.out.println(1);
      }
      Aoo(){
        System.out.println(2);
      }
    }
    class Boo extends Aoo{
      static{
        System.out.println(3);
      }
      Boo(){
        System.out.println(4);
      }
    }
 */

4,static final常量:应用率高

  • 必须声明同时初始化

  • 由类名点来访问,不能被改变

  • 建议:常量所有字母都大写,多个单词用_分隔

  • 编译器在编译时会常量直接替换为具体的数,效率高

  • 何时用:数据永远不变,并且经常使用

public class StaticFinalDemo {
    public static void main(String[] args) {
        System.out.println(Aoo.PI); //通过类名点来访问
        //Aoo.PI = 3.1415926; //编译错误,常量不能被改变


        //1)加载Boo.class到方法区中
        //2)静态变量num一并存储到方法区中
        //3)到方法区中获取num的值并输出
        System.out.println(Boo.num);

        //编译器在编译时会将常量直接替换为具体的值,效率高
        //相当于System.out.println(5);
        System.out.println(Boo.COUNT);

    }
}

class Boo{
    public static int num = 5; //静态变量
    public static final int COUNT = 5; //常量
}

class Aoo{
    public static final double PI = 3.14159;
    //public static final int NUM; //编译错误,常量必须声明同时初始化
}

 5,抽象方法:

  • 由abstract修饰
  • 只有方法的定义,没有具体的实现(连{}都没有)

6, 抽象类

  • 由abstract修饰

  • 包含抽象方法的类必须是抽象类,不包含抽象方法的类也可以声明为抽象类

  • 抽象类不能被实例化(new对象)

  • 抽象类是需要被继承的,派生类:

    • 重写所有抽象方法--------------------变不完整为完整(常用)
    • 也声明为抽象类-----------------------不常用
  • 抽象类的意义:

    • 封装共有的属性和行为-------------------代码复用

    • 为所有派生类提供统一的类型----------向上造型(代码复用)

    • 可以包含抽象方法,为所有派生类提供了统一的入口(能点出来),

      派生类的行为不同,但入口是一致的,同时相当于定义了一个标准

7, 设计规则:

  • 将派生类所共有的属性和行为,抽到超类中-----------------抽共性

  • 派生类的行为都一样,设计为普通方法

    派生类的行为都不一样,设计为抽象方法

8, 抽象方法/抽象类的疑问:

  • 抽象方法存在的意义是什么?

    • 保证当发生向上造型时,通过超类型的引用能点出来那个方法
  • 既然意义只在于能点出来,那为什么不设计为普通方法?

    • 若设计为普通方法,则派生类可以重写也可以不重写,而设计为抽象方法,可以强制派生类必须重写

      ------做了个标准,强制必须重写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值