面向对象基本概念(java)

面向对象基本概念

一、什么是面向对象:

  1. 面向对象是一种编程思想。
  2. 面向对象是一种思考问题的思维方式。

二、建立面向对象思维方式:

  1. 先整体,再局部
  2. 先抽象,再具体
  3. 能做什么,再怎么做

三、如何学习面向对象:

1.掌握一门面向对象语言的语法
2、熟悉面向对象的设计模式
3、熟悉面向对象设计模式

类与对象:

1、类是分类、类别。类是一组具有相同特性(属性)与行为(方法)的事务集合。
2、类表示一个共性的产物,是一个综合的特征,而对象,是一个个性的产物,是一个个体的特征。
3、类是由属性和方法组成:属性就相当于一个个的特征,方法就相当于人的一个个行为,例如:说话、吃饭、唱歌、睡觉。

类和对象的定义格式

在java中对象声明有两种含义:
声明对象:Horse horse=null;
//表示声明了一个对象,但是此对象无法使用,horse没有具体的内存指向

实例化对象:horse=new Horse( );
//表示实例化对象,可以使用

//通过对象调用方法
horse.eat()

//匿名对象调用方法
new Horse().eat()
【例子】

package HeadFirst;
/**

 */
public class Test14 {
    public static void main(String[] args) {
        Horse h=null;//声明一个类的变量(除了八种基本数据类型外,都是引用数据类型,包括数组)
        //创建一个Horse类型对象,实例对象
        h=new Horse();
        //有了对象,我们就可以调用对象的属性和方法
        h.name="赤兔马";
        h.age=350;
        h.run();//调用方法,那么方法就会被执行
        //匿名对象只能使用一次,用完后该对象就会被释放
        new Horse().run();
        h=null;//把对象释放
        //h.eat();//当对象不存在时,调用该对象的属性和方法将报错(空指针)
        
    }
}
//自定义一个类(类型)
class Horse{
    //类中定义属性(特征)
    String name;//字符串是引用类型变量,不是基本数据类型
    int age;
    public void run(){
        System.out.println("我是"+name+",我"+age+"了");
    }
}

类与对象小结

1、new关键字:表示向内存申请空间,也表示实例化一个对象,创建一个对象。
2、一个对象在内存中的大小,由该对象的所有属性所占的内存大小的总和。引用类型变量在32位系统上占4个字节,在64位系统上占8个字节
3、相同的类型才可以赋值
4、不同的引用,指向同一个对象,任何一个引用改变对象的值,其他引用都会反映出来
5、 编程时要注意的问题,在确定不使用对象时,要尽早释放对象:引用=null
6、当一个堆中的对象没有任何引用变量所指向时,该对象就会被JVM的GC程序认为是垃圾对象,从而被回收

面向对象封装性

成员变量和局部变量

1、在类中的位置不同
成员变量:在类中定义
局部变量:在方法中定义或方法的参数
2、在内存中的位置不同
成员变量:在堆内存(成员变量属于对象,对象进堆内存)
局部变量:在栈内存(局部变量属于方法,方法进栈内存)
3、生命周期不同
成员变量:随着对象的创建存在,随着对象的销毁而消失
局部变量:随着方法的调用存在,随着方法的调用完毕而消失
4、初始化值不同
成员变量:有默认初始化值,引用类型默认为null
局部变量:没有默认初始化值,必须定义,赋值,然后才能使用
注意:局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则
【例子】

package HeadFirst;
/*
封装性
如果属性没有封装,那么在本类之外创建对象后,可直接访问属性
private关键字:访问权限修饰符,public表示公有的,private表示私有的,私有的属性和方法,只能在本类中访问
公有的属性和方法,可以被类外部的其他类访问,想要在类外部访问私有属性,我们需要提供公有的方法来间接访问
通常在一个类中,属性都私有化,并对外提供setter and getter
 */
public class Test15 {
    public static void main(String[] args) {
        Person p1=new Person();
//        p1.name="菲菲";
//        p1.age=18;
        p1.setName("郎朗");
        p1.setAge(18);
    }
}
//没有封装之前
class Person{
//属性的封装
    private String name;
    private int age;

    //setter and getter
    //对外提供一个为name属性设置的方法
    public void setName(String name){
        this.name=name;
    }
    //对外提供一个获取name值的方法
    public String getName(){
        return name;
    }
    public void setAge(int age){
        //局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则
        this.age=age;//这里局部变量age与成员变量age一样,若不加this就会根据就近原则把age赋给局部变量自身,报错
    }
    public int getAge(){
        return age;
    }
    public void run(int len){//参数也是局部变量
        int dis=len;//m也是局部变量
        System.out.println("我跑了"+dis+"米");
//        int i;
//        System.out.println(i);//会报错,尚未初始化i,所以局部变量定义后需要赋值,不会有默认值
    }
        }

构造方法

构造方法小结
(1)构造方法名称与类名相同,没有返回值(包括void)
(2)构造方法用于初始化数据(属性)
(3)每一个类中都会有一个默认的无参的构造方法
(4)如果类中有显示的构造方法,那么默认的构造方法将无效
(5)如果有显示的构造方法,还想保留默认构造方法,需要显示的写出来
(6)构造方法可以有多个,但参数不一样,称为构造方法重载
(7)在构造方法中调用另一个构造方法,使用this(…),该句代码必须在第一句
(8)构造方法之间的调用,必须要有出口
(9)给对象初始化数据可以使用构造方法或setter方法,通常情况下,两者都会保留
(10)一个好的编程习惯是保留默认的构造方法。(为了方便一些框架代码使用反射来创建对象)
(11)private Dog( ){},构造方法私有化,当我们的需求是为了保证类只有一个对象时。
什么时候一个类只需要一个对象?比如,工具类(没有属性的类,只有行为)并且该工具对象被频繁使用。权衡只用一个对象与产生多个对象的内存使用,来确定该类是否要定义为只需要一个对象。
【代码】

package HeadFirst;
/*
构造方法:构造方法是在类中定义的,构造方法的定义格式:方法名称与类名称相同,无返回值类型的声明
 1构造方法就是类构造对象时调用的方法,用于对象的初始化工作
 2构造方法就是实例化一个类的对象时,也就是new的时候,最先调用的方法
 */
public class Test16 {
    public static void main(String[] args) {
Dog dog=new Dog();//不带参数的构造函数
Dog dog1=new Dog("wang wang",1);//带两个参数的构造函数
    }
}
class Dog{
    public Dog(){
        System.out.println("构造方法执行了");
    }
    public Dog(String name){
        this.name=name;
        System.out.println("带一个参数的构造方法执行了");
    }
    public Dog(String name,int age){
        this(name);//调用其他构造方法时,此语句需要在第一句,在构造方法相互调用时必须要有出口
       // this.name=name;
        this.age=age;
        System.out.println("带两个参数的构造方法执行了");
    }
    private String name;
    private int age;
    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
    public void setAge(int age){
        this.age=age;
    }
    public int getAge(){
        return age;
    }
}

this 关键字

【例子】

package HeadFirst;
/*
this关键字
调用类中的属性
调用类中的方法或构造方法
表示当前对象:在方法被调用过程中,哪个对象调用了方法,在方法内的this就表示谁
类名.this
 */
public class Test17 {
    public static void main(String[] args) {
Cat cat=new Cat();
cat.setName("咪咪");
cat.setAge(3);
cat.eat();
    }
}
class Cat{

    private String name;
    private int age;
    public void setName(String name){
        this.name=name;//this代表当前对象
    }
    public String getName(){
        return name;
    }
    public void setAge(int age){
        this.age=age;
    }
    public int getAge(){
        return age;
    }
    public void eat(){
        //在方法中使用this调用类中的其他方法或属性,this可省略,this前面可以使用当前的类名.this
        System.out.println("我是"+Cat.this.getName()+",我爱吃鱼");
        System.out.println("我是"+this.name+",我爱吃鱼");

    }
}

值传递与引用传递

【例子】

package HeadFirst;
//值传递
public class ValueDemo {
    public static void main(String[] args) {
        int x=10;
        method(x);
        System.out.println("x="+x);//所以输出还是10
    }
    public static void method(int mx){
        mx=20;//改的是mx不是x
    }
}

package HeadFirst;
//引用传递
public class RefDemo1 {
    public static void main(String[] args) {
        Duck d=new Duck();
        method(d);//d里面存的是地址,将d的地址赋给duck
        System.out.println("Duck age="+d.age);//输出是5
    }
    public static void method(Duck duck){
        duck.age=5;
    }
}
class Duck{
    int age=2;//省略封装
}

package HeadFirst;
//String传递
//字符串本身就是一个对象
public class RefDemo2 {
    public static void main(String[] args) {
        String name="小飞";//一个对象
        method(name);//name中存的是地址,将name地址赋给sname,sname也指向对象“小飞”
        System.out.println("name="+name);
    }
    public static void method(String sname){
        sname="小备";//这又是一个对象,使得sname指向对象“小备”,
    }
}

package HeadFirst;
//String传递
public class RefDemo3 {
    public static void main(String[] args) {
        Person1 p= new Person1();
        method(p);
        System.out.println("Person1 name="+p.name);
    }
    public static void method(Person1 per){
        per.name="备备";
    }
}
class Person1{
    String name="飞飞";//省略封装
}

对象的一对一关系

【例子】

package HeadFirst;

public class Test18 {
    public static void main(String[] args) {
        Hero hero=new Hero("刘备",300);
        Weapon weapon=new Weapon("双股剑",3);
        //把两个对象关联起来
        hero.setWeapon(weapon);
        weapon.setHero(hero);
        //通过英雄来获取他的信息
        String name=hero.getName();
        int age=hero.getAge();
        Weapon w=hero.getWeapon();
        System.out.println("我是"+name+",我"+age+"岁,我的武器是:"+w.getName()+",排行"+w.getGrade()+"级");
    }
}
//英雄类
class Hero{
    private String name;
    private int age;
    private Weapon weapon;//一对一关系
    public void setWeapon(Weapon weapon){
        this.weapon=weapon;
    }

    public Weapon getWeapon() {
        return weapon;
    }
    public Hero(){}
    public Hero(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
    public void setAge(int age){
        this.age=age;
    }
    public int getAge(){
return age;
    }
}
//兵器类
class Weapon{
    private String name;
    private int grade;
    private Hero hero;
    public void setHero(Hero hero){
        this.hero=hero;
    }
    public Hero getHero(){
        return hero;
    }
    public Weapon(){}
    public Weapon(String name,int grade){
        this.name=name;
        this.grade=grade;
    }
    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
    public void setGrade(int grade){
        this.grade=grade;
    }
    public int getGrade(){
        return grade;
    }
}
#我是刘备,我300岁,我的武器是:双股剑,排行3

static 关键字

static关键字作用:
1、使用static关键字修饰一个属性
声明为static的变量实质上就是全局变量
2、使用static关键字修饰一个方法
通常,在一个类中定义一个方法为static,那就是说,无需本类对象即可调用此方法
3、使用static关键字修饰一个类(内部类)
【例子】

package HeadFirst;

/*
static关键字
1静态变量或方法不属于对象,依赖类
2静态变量是全局变量,生命周期从类被加载后一直到程序结束
3静态变量只有存一份,在静态方法区中存储
4静态变量是本类所有对象共享一份
5建议不要使用对象名去调用静态变量,直接使用类名调用
6static修饰一个方法,那么该方法属于类,不属于对象,直接使用类名调用
 */
public class Test19 {
    public static void main(String[] args) {
//Role bei=new Role("刘备","蜀国");
//Role fei=new Role("张飞","蜀国");
//Role yu=new Role("关羽","蜀国");
        Role bei = new Role("刘备");
        Role fei = new Role("张飞");
        Role yu = new Role("关羽");
        System.out.println(bei.getInfo());
        System.out.println(fei.getInfo());
        System.out.println(yu.getInfo());
        System.out.println("-------------------");
        System.out.println(bei.country);//去掉country前面的private
        System.out.println(fei.country);
        System.out.println(yu.country);
        System.out.println("-------------------");
        bei.country = "秦国";
        System.out.println(bei.country);
        System.out.println(fei.country);
        System.out.println(yu.country);
        System.out.println("-------------------");
        System.out.println(Role.country);

    }
}

//角色
class Role {
    private String name;
    // private String country;
    static String country="蜀国";//将country定义成静态变量,(去掉前面的private)

    //    public Role(String name,String country){
//        this.name=name;
//        this.country=country;
//    }
    public Role(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
/*
    public void setCountry(String country) {
        this.country = country;
    }

    public String getCountry() {
        return country;
    }
*/
    public String getInfo() {
        return "name:" + name + ",country:" + country;
    }
}
#name:刘备,country:蜀国
#name:张飞,country:蜀国
#name:关羽,country:蜀国
#-------------------
#蜀国
#蜀国
#蜀国
#-------------------
#秦国
#秦国
#秦国
#-------------------
#秦国

【注意】
声明为static的方法有以下几条限制:
它们仅能调用其他的static方法
它们只能访问static数据
它们不能以任何方式引用this或super
什么时候使用static?
所有对象共同的属性或方法,那么我们应该定义为静态的

main方法分析

主方法:
public static void main(String [] args){
//代码块
}
public:公有的,最大的访问权限
static:静态的,无需创建对象
void:表示没有返回值,无需向JVM返回结果
main:方法名,固定的方法名
String[] args:表示参数为字符串数组,可以在调用方法时传入参数

【代码】

package HeadFirst;
/*
代码块:
1普通代码块:在方法中写的代码块
2构造块:是在类中定义的代码块,在创建对象时被调用,优于构造方法执行
3在类中使用static声明的代码块称为静态代码块
在第一次使用的时候被调用(创建对象),只会执行一次,优于构造块执行
我们在项目开发中,通常会使用静态代码块来初始化只调用一次的数据
小结:重点会使用的顺序是静态代码块,普通代码块,同步代码块,构造代码块
 */
public class Test20 {
    public static void main(String[] args) {
    Student s=new Student();
    Student s1=new Student();
    }
}
class Student{
    public Student(){
        System.out.println("构造方法");
    }
    static {
        System.out.println("我是静态构造块");
    }

    {
        System.out.println("我是构造代码块");
    }
    public void study(){
        //限制作用域
        {
        int i=10;
        System.out.println("我是普通代码块");
        }
    }
}
#我是静态构造块
#我是构造代码块
#构造方法
#我是构造代码块
#构造方法

单例设计模式

单例设计模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点
1构造方法私有化
2声明一个本类对象
3给外部提供一个静态方法获取对象实例
两种实现方式:
1饿汉式
2懒汉式
【例子】

package HeadFirst;

/*
单例设计模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点
1构造方法私有化
2声明一个本类对象
3给外部提供一个静态方法获取对象实例
两种实现方式:
1饿汉式:在第一次调用getInstance方法时,对象被创建,到程序结束后释放
2懒汉式:在类被加载后,对象被创建,到程序结束后释放
在项目中为什么要使用单例,单例有什么好处?
1在设计一些工具类的时候(通常工具类,只有功能方法,没有属性)
2工具类可能会被频繁调用
目的是为了节省重复创建对象所带来的内存消耗,从而来提高效率

能不能使用构造方法私有化+静态方法来替换单例?
 */
public class Test21 {
    public static void main(String[] args) {
        //Singleton1 s=new Singleton1();//构造方法私有化,故会出错
        Singleton2 s = Singleton2.getInstance();//故通过静态方法获取对象实例
        s.print();
        Singleton2 s2 = Singleton2.getInstance();
        s2.print();
        System.out.println(s==s2);//结果为true说明这两个对象是一样的,因为对象是静态的
    }
}
//使用构造方法私有化+静态方法来实现工具类,比如Math
class Tools{
    private Tools(){};
    public static void print1(){

    }
    public static void print2(){

    }
}

//饿汉式:占用内存时间长,提高效率
class Singleton1 {
    private Singleton1() {
    }//构造方法私有化

    private static Singleton1 s = new Singleton1();//声明一个本类对象,对象是静态的说明只会执行一次

    public static Singleton1 getInstance() {//给外部提供一个静态方法获取对象实例
        return s;
    }

    public void print() {
        System.out.println("测试方法");
    }
}
//懒汉式:占用内存时间短,效率稍低(程序里多了个判断)
class Singleton2{
    private Singleton2(){
    }
    private static Singleton2 s;
    public static Singleton2 getInstance(){
        if(s==null){
            s=new Singleton2();
        }
        return s;
    }
    public void print(){

        System.out.println("测试方法2");
    }
}

对象数组与管理

【例子】

package HeadFirst;
import java.util.Arrays;
/*
对象数组与管理
使用对象数组实现多个Chicken的管理
动态数组:
1数组是一种线性数据结构
2数组不适合作删除插入等操作,适合添加,查找,遍历
 */
public class Test22 {
    public static void main(String[] args) {
        ChickenManager cm = new ChickenManager(5);
        cm.add(new Chicken(1, "一", 10));
        cm.add(new Chicken(2, "二", 8));
        cm.add(new Chicken(3, "三", 6));
        cm.add(new Chicken(4, "四", 4));
        cm.add(new Chicken(5, "五", 2));
        cm.add(new Chicken(6, "六", 1));
        System.out.println("数组的长度是:" + cm.length());
        System.out.println("----------printAll-----------");
        cm.printAll();
        System.out.println("-----------find-----------");
        Chicken c = cm.find(5);
        c.print();
        System.out.println("----------update------------");
        cm.update(new Chicken(1,"母鸡",20));
        cm.printAll();
        System.out.println("----------delete------------");
         cm.delete(3);
         cm.printAll();
    }
}

//小鸡管理类
class ChickenManager {
    private Chicken[] cs = null;
    int count = 0;//记录当前数组元素的个数

    public ChickenManager(int size) {
        if (size > 0) {
            cs = new Chicken[size];
        } else {
            cs = new Chicken[5];
        }
    }

    public int length() {
        return cs.length;
    }

    //添加:实现动态数组
    public void add(Chicken c) {
        if (count >= cs.length) {//数组已满,需要扩充
            //算法1:扩充原来数组大小的一半,cs.length*3/2+1
            //算法2:扩充原来数组的一倍,cs.length*2
            int newLen = cs.length * 2;
            cs = Arrays.copyOf(cs, newLen);//将原先cs中的元素挨个复制到新扩充的数组中
        } else {
            cs[count] = c;
            count++;
        }
    }

    //删除
    public void delete(int id) {
        for(int i=0;i<count;i++){
            if(cs[i].getId()==id){
                //找到了要删除的对象,把该对象之后的对象向前移动一位
                for(int j=i;j<count-1;j++){
                    cs[j]=cs[j+1];
                }
                //把最后一个对象赋值为空(删除)
                cs[count-1]=null;
                count--;//
                break;
            }
        }

    }

    //更新
    public void update(Chicken c) {
        Chicken temp=find(c.getId());
        if(temp!=null){
            temp.setName(c.getName());
            temp.setAge(c.getAge());
        }
    }

    //查找
    public Chicken find(int id){
        for (int i = 0; i < count; i++) {
            if (cs[i].getId() == id) {
                return cs[i];
            }
        }
        return null;
    }

    //输出所有
    public void printAll() {
        for (int i = 0; i < count; i++) {
            cs[i].print();
        }
    }
}

//小鸡类
class Chicken {
    private int id;
    private String name;
    private int age;

    public Chicken() {
    }//一般情况下最好保留默认的构造方法

    public Chicken(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void print() {
        System.out.println("id=" + id + ",name=" + ",age" + age);
    }
}
数组的长度是:10
----------printAll-----------
id=1,name=,age10
id=2,name=,age8
id=3,name=,age6
id=4,name=,age4
id=5,name=,age2
-----------find-----------
id=5,name=,age2
----------update------------
id=1,name=,age20
id=2,name=,age8
id=3,name=,age6
id=4,name=,age4
id=5,name=,age2
----------delete------------
id=1,name=,age20
id=2,name=,age8
id=4,name=,age4
id=5,name=,age2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值