Java基础02-对象

对象
  • Java中所有对象都是new出来的,所有对象的内存都是在堆空间,所有保持对象的变量都是引用类型
  • Java运行时环境有个垃圾回收器,会自动回收不再使用的内存
一. 构建方法
  • 构造方法
    • 函数名相同,参数名不同,可以重载
    • 构造方法如果想调用别的构造方法,必须放在第一行
    • 如果一个类没有自定义构造方法,系统会默认无参构造方法
  • 成员变量的初始化
    • 编译器会自动为未初始化的成员变量设置初始化值,比如int属性初始化值为0
    • 如何手动给实例变量提供初始值?
      • 在声明中
      • 在构造方法中
      • 在初始化块中
      • 编辑器会将初始化块复制到每个构造方法的头部(每创建一个实例对象,就会执行一次初始化代码块)
    • 如何手动给类变量提供初始值?
      • 在声明中
      • 在静态初始化块中
        当一个类被初始化的时候执行静态初始化块
        当一个类第一次被主动使用时,JVM会对类进行初始化
//this,this是一个隐藏的,位置最靠前的方法参数
public class person {
    public int age = 10;
    protected float weight;
    float height;
    private float salary;
    public static int count;
    
	//set
    public void setAge(int age) {
        this.age = age;
    }
    //get
    public int getAge() {
        return age;
    }
    //构造
    public person() {
        age = 10;
        weight = 10.f;
        height = 50.f;
        salary = 10000.f;
    }
    //初始化代码块 在构造函数前执行
	{
		weight = 100.f;
		height = 100.f;
	}
	//静态初始化代码块 在构造函数前执行
	static {
		count = 1;
	}
	
    //toString 重写此方法可以打印出对象参数详细信息
    @Override
    public String toString() {
        return "person{" +
                "age=" + age +
                ", weight=" + weight +
                ", height=" + height +
                ", salary=" + salary +
                '}';
    }

    public static void main(String[] args) {
        person p = new person();
        System.out.println(p);
    }
}
二. 包
  • Java中的包就是其他编程语言中的命名空间,包的本质就是文件夹,常见作用是
    • 将不同的类进行组织管理、访问控制
    • 解决命名冲突
  • 包名写法建议
    • com.域名.***
    • 包名全小写
  • 导包
    • #import java.lang.*即导入java.lang当前文件夹下所有文件,不包含其子文件夹下的文件
三. 继承(Inheritance)
  • 任何类最终都继承自java.lang.object
  • 子类可以定义跟父类同名的成员变量(但不推荐)
public class person {
}
//子类
public class student extends person{
}
四. 方法重写(Override)
  • 子类的方法签名与父类一样。也叫做覆盖,重写
  • 子类override的方法权限必须≥父类的方法权限
  • 子类override的方法返回值类型必须≤父类的方法返回值类型
@Override
public void Method() {
}
五. 注解(Annotation)
  • @关键字(值),用于把关键字和值传递给编译器,更精确低控制编译器的动作。关键字都是随技术、框架、编译器的不同而不同,含义也不同、数量不定。可以由子技术或开发者扩充。比如
    • @Override:告诉编辑器这是一个重写后的方法
    • @SuppressWarnings(“警告类别”),作用:让编译器不生成警告信息;
    • @SuppressWarnings({“警告类别”,“警告类别”})
      • 比如:@SuppressWarnings(“unused”) 所有unused的警告不会再报了
六. 访问控制(Access Control)
  • Java中有4个级别的访问权限,从高到低如下所示
  • public:在任何地方都是可见的
  • protected:仅在自己的包中、自己的子类(包含其他包)中可见
  • 无修饰符/默认修饰符(package-private):仅在自己的包中可见
  • private:仅在自己的类中可见
七. static常用来修饰类的成员:成员变量,方法,嵌套类
  • 成员变量
    • 被static修饰:类变量,静态变量,静态字段
      • 在程序运行过程中只占用一份固定的内存(存储在方法区)
      • 可以通过实例、类访问
    • 没有被static修改:实例变量
      • 在每个实例内部都有一份内存
      • 只能通过实例访问,不可以通过类访问
  • 方法
    • 被static修饰:类方法,静态方法
      • 内部不能使用this
    • 未被static修饰:实例方法
      • 只能使用实例访问
    public static float height = 180.f;
    private static final float count = 10.f;
    
    public static void Mehtod(String[] args) {
    }
    private static String showName(int count) {
        return "name";
    }
八. 静态导入
  • 使用静态导入后,就可以省略类名来访问静态成员(成员变量、方法、嵌套类)
  • 正确使用静态导入,可以消除一些重复的类名,提高代码可读性
  • 过度使用静态导入,会让读者分不清静态成员是在哪个类中定义的
  • 谨慎使用
package com.mj.other;

public class Test {
    public static int age = 1;
    public static void show() {
        System.out.println("age is" + age);
    }
    public static class OtherClass {
        public void other() {
            System.out.println("other");
        }
    }
}

//导入
package com.mj;
import static com.mj.other.Test.*;

public class main {
    public static void main(String[] args) {
        System.out.println(age);
        show();
        OtherClass other = new OtherClass();
        other.other();
    }
}

//经典使用场景
//Math.PI
package com.mj;

import static java.lang.Math.PI;

public class main {
    public static void main(String[] args) {
        System.out.println(2*PI*10);
    }
}
九. 单例模式
  • 饿汉式单例模式
public class Rocket {
    //私有的静态的实例变量
    private static Rocket instance = new Rocket();
    //构造方法私有化
    private Rocket() {}
    //公共的静态的方法,返回唯一的那个实例
    public static Rocket getInstance() {
        return instance;
    }
}
  • 懒汉式单例模式
public class Rocket {
    private static Rocket instance = null;
    private Rocket() {}
    /**
    * 这个方法并非线程安全
    * 多条线程同时执行
    * */
    public static Rocket getInstance() {
        if (instance == null) {
            instance = new Rocket();
        }
        return instance;
    }
}
	
//调用
	Rocket r1 = Rocket.getInstance();
	Rocket r2 = Rocket.getInstance();
	System.out.println(r1 == r2);
十. _final_常量(constant)
  • 被final修饰的类:不能被继承
    • 被final修饰的方法:不能被重写
    • 被final修饰的属性:只能赋值一次
  • 常量(constant)
    • 编译器优化:编译时就能确定值的,会直接替换;称为编译时常量
  • 常理写法
	//大写
    private static final int AGE = 1;
    public static void main(String[] args) {
        System.out.println(AGE);
        //直接替换为10,相当于宏替换
        System.out.println(10);
    }
十一. 嵌套类(Nested Class)
  • 嵌套类:定义在另一个类中的类
    • 在嵌套类外层的类,称为:外部类(Outer Class)
    • 最外层的外部类,称为:顶级类(Top-level Class)
  • 内部类:没有被static修饰的嵌套类,非静态嵌套类
    • 跟实例变量、实例方法一样,内部类与外部类的实例相关联
      • 必须先创建外部类实例,然后再用外部类实例创建内部类实例
      • 内部类不能定义除编译时常量以外的任何static成员
    • 内部类可以直接访问外部类中的所有成员(即使被声明为private)
    • 外部类可以直接访问内部类实例的成员变量、方法(即使被声明为private)
//内部类
public class Person {
    private int age = 18;
    private float height = 180.f;

    public int getAge() {
        return age;
    }

    public class Hand {
        private int weight;
        //编译时常量 final
        private static final double lengths = 0.5;

        public void show() {
            System.out.println(age);
        }

        public float showHeight() {
            return height;
        }
    }
}
//调用
public class main {
    public static void main(String[] args) {

        Person pModel = new Person();
        Person.Hand hand = pModel.new Hand();

        hand.show();
        System.out.println(hand.showHeight());

    }
}
  • 静态嵌套类:被static修饰的嵌套类
    • 静态嵌套类再行为上就是一个顶级类,只是定义的代码写在了另一个类中
    • 对比一般的顶级类,静态嵌套类多了一些特殊权限
      • 可以直接访问外部类中除实例变量、实例方法外的其他成员(即使被声明为private)
//静态嵌套类
public class Person {
    private int age = 18;
    private static int count = 100;
    private static void run() {
    }

    public static class Car {

        public void doSomethings() {
            Person person = new Person();
            System.out.println(person.age);

            System.out.println(Person.count);
            Person.run();
        }
    }
}
//调用
public class main {
    public static void main(String[] args) {
        Person.Car car = new Person.Car();
        car.doSomethings();
    }
}
  • 什么情况使用嵌套类?

    • 如果类A只用在类C内部,可以考虑将类A嵌套到类C中
      • 封装性更好
      • 程序包更加简化
      • 增强可读性、维护性
    • 如果类A需要经常访问类C非公共成员,可以考虑将类A嵌套到类C中
      • 另外也可以根据需要将类A隐藏起来,不对外暴露
    • 如果需要经常访问非公共的实例成员,设计成内部类(非静态嵌套类),否则设计成静态嵌套类
      • 如果必须先有C实例,才能创建A实例,那么可以将A设计为C的内部类
  • 局部类(Local Class):定义在代码块中的类(可以定义在方法中、for循环中、if语句中等)

    • 局部类不能定义除编译时常量以为的任何static成员
    • 局部类只能访问final或者有效final(有效final:只赋过一次值)的局部变量
      • 从Java8开始,如果局部变量没有被第二次赋值,就认定为有效final
    • 局部类可以直接访问外部类中的所有成员(即使被声明为private)
public class Person {
    private static float height = 180.f;
    float count = 10.f;

    public void doSomething() {
        for (int i = 0; i < 10; i++) {
            class ClassA {
                int age = 1;
                void test() {
//局部类可以获取外部类的有效final属性,即没有再次赋值的属性
                    System.out.println(height);
                    System.out.println(count);
                }
            }
            ClassA a = new ClassA();
            a.test();
        }
    }
}
//调用
public class main {
    public static void main(String[] args) {
        Person person = new Person();
        person.doSomething();
    }
}
十二. 抽象类(Abstract Class)
  • 抽象方法(Abstract Method)
public abstract class AbstractModel {
    public abstract void doSomething();
}
  • 抽象类:被abstract修饰的类
    • 可以定义抽象方法
    • 不能实例化,但可以自定义构造方法
    • 子类必须实现抽象父类中的所有抽象方法(除非子类也是一个抽象类)
    • 可以像非抽象类一样定义成员变量、常量、嵌套类型、初始化块、非抽象方法等
  • 也就是,抽象类也可以完全不定义抽象方法
//一级
public abstract class AbstractModel {
    public int p1 = 10;
    public double p2 = 100.0;
    public abstract void test1();
    public abstract void test2();
}
//二级
public abstract class AbstractSubModel extends AbstractModel {
    @Override
    public void test1() {
    }
}
//三级
public class ThrAbstractSubModel extends AbstractSubModel{
    @Override
    public void test1() {
        super.test1();
    }
    @Override
    public void test2() {
    	//TO DO Something
    }
}
  • 常见使用场景
    • 抽取子类的公共实现到抽象父类中,要求子类必须要单独实现的定义成抽象方法
十三. 接口(Interface)
  • Java中的接口
    • 一系列方法声明的集合
    • 用来定义规范、标准
  • 接口中可以定义的内容
    • 可以定义:抽象方法、常量、嵌套类型,从Java8开始可以定义:默认方法、静态方法(类方法)
    • 上诉可以定义的内容都是隐式public的,因此可以省略public关键字
    • 从Java9开始可以定义private方法
    • 常量可以省略static、final
    • 抽象方法不能省略abstract
    • 不能自定义构造方法、不能定义(静态)初始化块、不能实例化
  • 接口的细节
  • 接口名称可以在任何使用类的地方使用
  • 一个类可以通过implements关键字实现一个或多个接口
    • 实现接口的类必须实现接口中定义的所有抽象方法,除非它是个抽象类
    • 如果一个类实现的多个接口中有相同的抽象方法,只需要实现此方法一次
    • extends和implements可以一起使用,implements必须写在extends的后面
    • 当父类、接口中的方法签名一样时,那么返回值也必须一样。
  • 一个接口可以通过extends关键字继承一个或者多个接口
    • 当多个父接口中的方法签名一样时,那么返回值类型也必须一样
//1.抽象类 People(人)
public abstract class People {
    public abstract void eat();
}
//2.接口 Helperable(助手)
public interface Helperable {
//    常量可以省略static、final
//    (public static) int age = 20;
    public abstract void Programming(Child child);
    public abstract void Shopping(Child child);
    void cook(Child child);
}
//3.实现类 老师(Teacher)
public class Teacher extends People implements Helperable {
    @Override
    public void Programming(Child child) {
        System.out.println("Teacher help " + child.getName() + " programming ");
    }
    @Override
    public void Shopping(Child child) {
        System.out.println("Teacher help " + child.getName() + " Shopping ");
    }
    @Override
    public void cook(Child child) {
    }
    @Override
    public void eat() {
   }
}
//实现类 Rocket(机器人)
public class Rocket implements Helperable {
    private Child child;

    @Override
    public void Programming(Child child) {
        System.out.println("Rocket help " + child.getName() + " programming ");
    }
    @Override
    public void Shopping(Child child) {
        this.child = child;
        System.out.println("Rocket help " + child.getName() + " Shopping ");
    }
    @Override
    public void cook(Child child) {
    }
}
//4.调用类 child(儿童)
public class Child {
    private String name;
    private Helperable helperable;

    public Child(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setTelperable(Helperable helperable) {
        this.helperable = helperable;
    }
    public void needHelp() {
        helperable.Programming(this);
        helperable.Shopping(this);
    }
}
//5.main方法调用
    public static void main(String[] args) {
        Child child = new Child("jack");
        child.setTelperable(new Rocket());
        child.study();
    }
  • 抽象类和接口的用途海慧寺有点类似,该如何选择?
  • 何时选择抽象类?
    • 在紧密相关的类之间共享代码
    • 需要除public之外的访问权限
    • 需要定义实例变量、非final的静态变量
  • 何时选择接口?
    • 不相关的类实现相同的方法
    • 只是定义行为,不关心具体是谁实现了行为
  • 接口升级
    • 如果接口需要升级,比如添加新的抽象方法
      • 会导致大幅的代码改动,以前实现接口的类都得改动
    • 若想在不改动以前实现类的前提下进行接口升级,从java8开始,有2种方案
      • 1.默认方法
      • 2.静态方法
public interface Helperable {
    //常量可以省略static、final
//    (public static) int age = 20;
//    public static int age2 = 20;
    public abstract void Programming(Child child);
    public abstract void Shopping(Child child);
    void cook(Child child);
    
    
    //    默认方法
    //    用default修饰默认方法
    //    默认方法只能是实例方法
    default void eatable(Child child) {
        System.out.println("help " + child.getName() + " eat ");
    }

    //    静态方法
    static void sleepable(String name) {
        System.out.println("help " + name + " sleep ");
    }
}
十四. 多态(Polymorphism)
  • 什么是多态?
    • 具有多种形态
    • 同一操作作用于不同的对象,产生不同的执行结果
  • 多态的体现
    • 父类(接口)类型指向子类对象
    • 调用子类重写的方法
  • JVM会根据引用变量指向的具体对象来调用对应的方法
    • 这个行为叫做:虚方法调用(virtual method invocation)
    • 类似于C++中的虚函数调用
  • instanceof
    • 可以通过instanceof判断某个类型是否属于某种类型
十五. 匿名类

后续。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值