Java面向对象

Java面向对象

一、面向对象基础

1.基本概念

面向对象(Object Oriented)是软件开发方法。面向对象的概念和应用已超越了程序设计和软件开发,是一种对现 实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。 面向对象是相对于面向过程来讲的,指的是把 相关的数据和方法组织为一个整体 来看待,从更高的层次来进行系 统建模,更贴近事物的自然运行模式。

面向过程到面向对象思想层面的转变:

面向过程关注的是执行的过程,面向对象关注的是具备功能的对象。 面向过程到面向对象,是程序员思想上 从执行者到指挥者的转变。 此概念如果直接去理解的话可能会比较抽象,因为大家缺少对原始的面向过程的开发语言的了解.

2.三大思想

面向对象思想从概念上讲分为以下三种:OOA、OOD、OOP

OOA:面向对象分析(Object Oriented Analysis)

OOD:面向对象设计(Object Oriented Design)

OOP:面向对象程序(Object Oriented Programming)

3.三大特征

封装性:所有的内容对外部不可见

继承性:将其他的功能继承下来继续发展

多态性:方法的重载本身就是一个多态性的体现

4.类的定义格式

class 类名称{
成员属性
成员方法
}

5.属性方法

class 类名称{ 成员属性 成员方法 }
属性定义格式:

数据类型 属性名;

属性定义并赋值的格式:

​ 数据类型 属性名 = 初始化值;

方法定义格式:

权限修饰符 返回值类型 方法名(形式参数列表){

​ //方法体

​ return 返回值;

}

6.对象的创建和使用

一个类要想真正的进行操作,则必须依靠对象,对象的定义格式如下:

类名称 对象名称 = new 类名称() ;

​ 如果要想访问类中的属性或方法(方法的定义),则可以依靠以下的语法形式:
访问类中的属性: 对象.属性 ;

调用类中的方法: 对象.方法(实际参数列表) ;

7.方法的重载

一个类, 可以存在多个构造方法 :
参数列表的长度或类型不同即可完成构造方法的重载

构造方法的重载 ,可以让我们在不同的创建对象的需求下, 调用不同的方法来完成对象的初始化!

8.匿名对象

没有对象名称的对象 就是匿名对象。

匿名对象只能使用一次,因为没有任何的对象引用,所以将称为垃圾,等待被G·C回收。
只使用一次的对象可以通过匿名对象的方式完成,这一点在以后的开发中将经常使用到

9.栈和堆

Java栈的区域很小,大约2m左右,特点是存取速度快
栈存储的特点是先进后出

存储的是:  
基本数据类型的数据 以及 引用数据类型的引用!

例如: 

int  a  =10;

Person p = new Person();

10存储在栈内存中 ,  第二句代码创建的对象的引用(p)存在栈内存中

存放的是类的对象 
 
Java是一个纯面向对象语言, 限制了对象的创建方式: 
 
        所有类的对象都是通过new关键字创建
 
new关键字, 是指告诉JVM , 需要明确的去创建一个新的对象 , 去开辟一块新的堆内存空间: 
 
堆内存与栈内存不同, 优点在于我们创建对象时 , 不必关注堆内存中需要开辟多少存储空间 , 也不需要关注内存占用 时长 !
 
堆内存中内存的释放是由GC(垃圾回收器)完成的 
 
 
垃圾回收器 回收堆内存的规则: 
 
    当栈内存中不存在此对象的引用时,则视其为垃圾 , 等待垃圾回收器回收 !
 
 
例如:
Person p0 = new Person(); 
Person p1 = p0;
Person p2 = new Person();

二、面向对象进阶

1.封装

 观察如下代码:
     class Person{
     
         private String name ;       // 表示姓名
         private int age ;           // 表示年龄
         void tell(){
     
             System.out.println("姓名:" + name + ";年龄:" + age);
         }
     };
	public class Demo{
     
    	public static void main(String args[]){
     
        	Person per = new Person() ;
       		per.name = "张三" ;
        	per.age = -30 ;
        	per.tell() ;
    	}
    };
 
以上的操作代码并没有出现了语法错误,但是出现了逻辑错误 (年龄-30岁)
 
在开发中, 为了避免出现逻辑错误, 建议对所有属性进行封装,并为其提供set及get方法进行设置和取得操作。
 
修改代码如下
class Person{
     
    private String name ;       // 表示姓名
    private int age ;           // 表示年龄
    void tell(){
     
       System.out.println("姓名:" + getName() + ";年龄:" + getAge());     }
    public void setName(String str){
     
        name = str ;
    }
    public void setAge(int a){
     
        if(a>0&&a<150)
            age = a ;
    }
    public String getName(){
     
        return name ;
    }
    public int getAge(){
     
        return age ;
    }
};
public class OODemo10{
     
    public static void main(String args[]){
     
        Person per = new Person() ;
        per.setName("张三") ;
        per.setAge(-30) ;
        per.tell() ;
    }
};

2.this

在Java基础中,this关键字是一个最重要的概念。使用this关键字可以完成以下的操作:
· 调用类中的属性
· 调用类中的方法或构造方法
· 表示当前对象

3.static

static表示“静态”的意思,可以用来修饰成员变量和成员方法(后续还会学习 静态代码块 和 静态内部类)。
static的主要作用在于创建独立于具体对象的域变量或者方法

简单理解:
被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。
并且不会因为对象的多次创建而在内存中建立多份数据

重点:

  1. 静态成员 在类加载时加载并初始化。
  2. 无论一个类存在多少个对象 , 静态的属性, 永远在内存中只有一份( 可以理解为所有对象公用 )
  3. 在访问时: 静态不能访问非静态 , 非静态可以访问静态 !

4.代码块

普通代码块
在执行的流程中出现的代码块, 我们称其为普通代码块。

构造代码块
在类中的成员代码块, 我们称其为构造代码块, 在每次对象创建时执行, 执行在构造方法之前。

静态代码块
在类中使用static修饰的成员代码块, 我们称其为静态代码块, 在类加载时执行。 每次程序启动到关闭 ,只会 执行一次的代码块。

构造方法 与 构造代码块 以及 静态代码块的执行顺序:
静态代码块 --> 构造代码块 --> 构造方法

5.权限修饰符

Java面向对象_第1张图片

6.main方法详解

main()方法:
public static void main(String args[])
	以上的各个参数的含义如下:
    	· public:表示公共的内容,可以被所有操作所调用
        · static:表示方法是静态的,可以由类名称直接调用。java StaticDemo09         · void:表示没有任何的返回值操作
        · main:系统规定好的方法名称。如果main写错了或没有,会报错:NoSuchMethodError: main        
        · String[] args:字符串数组,接收参数的
 
 
public class StaticDemo10{
	public static void main(String args[]){
    	for(int i=0;i

7.单例设计模式

单例设计模式是我学习的第一个设计模式,也是比较重要的一个设计模式,今天,我们就学习单例设计模式的两种实现方式。
单例设计模式:保证程序在内存中只有一个对象存在(被程序所共享)

单例设计模式的两种实现方式:
一、懒汉式:随着类的加载在内存中对象为null,当调用 getInstance 方法时才创建对象(延迟加载)
二、饿汉式:随着类的加载直接创建对象(推荐开发中使用)
单例设计模式的实现步骤:
1.保证一个类只有一个实例,实现方式:构造方法私有化
2.必须要自己创建这个实例,实现方式:在本类中维护一个本类对象(私有,静态)
3.必须向整个程序提供这个实例,实现方式:对外提供公共的访问方式(getInstance方法,静态)

懒汉式实现如下:

class Single{
     
    private Single(){
     
    }
    private static Single s1 = null;    
    public static Single getInstance(){
     
            if(s1 == null){
     
                  s1 = new Single();
            }
                   return s1;
    }
 }

饿汉式实现如下:

 class Single2{
     
     private Single2(){
     
     }
 	  private static Single2 s = new Single2();
  	  public static Single getInstance(){
     
  	          return s;
  	  }
  	  void print(){
     
  	          System.out.println("Hello World!");
  	  }
 }

三、面向对象高级

1.继承格式

class 父类{
     
    
}

class 子类 extends 父类 {
     
    
}

继承父类的成员变量、成员方法等

2.super

1.通过super, 可以访问父类构造方法

2.通过super,可以访问父类的属性

3.通过super,可以访问父类的方法

class Student extends Person{
     
    
    public Student() {
     
        //调用super构造方法的代码,必须写在子类构造方法的第一行
        super("无名称",1);
        super.sex = '男';//super的非构造方法可以不在第一行
    }
}

3.重写(Override)与重载(Overload)的区别

1.发生的位置:
重载:一个类中
重写:子父类中
2.参数列表限制:
重载:必须不同
重写:必须相同
3.返回值类型:
重载:与返回值类型无关
重写:返回值类型必须一致
4.访问权限:
重载:与访问权限无关
重写:子类的方法权限必须不小于父类的方法权限
5.异常处理
重载:与异常无关
重写:异常范围可以更小,但是不能抛出新的异常。

4.final关键字

final关键字
final用于修饰属性
变量成为了常量,无法对其再次进行赋值
final修饰的局部变量,只能赋值一次(可以先声明否赋值)
final修饰的成员变量,必须在声明时赋值
final用于修饰类
final修饰的类不能被继承
final用于修饰方法
final修饰的方法不能被重写

常量的命名规范:
由多个单词组成,单词与单词之间使用_隔开,所以单词大写
例如:SQL_INSERT

public class Demo1 {
     
    
    public static void main(String[] args) {
     
        final int a = 10;//后面不能改值
    }
}

5.抽象类

5.1概念

抽象类必须使用abstract class声明
一个抽象类中可以没有抽象方法。抽象方法必须写在抽象类或者接口中。

格式:
abstract class 类名{ // 抽象类
}

5.2抽象方法

只声明而未实现的方法称为抽象方法(未实现指的是:没有“{}”方法体),抽象方法必须使用abstract关 键字声明。
格式:
abstract class 类名{ // 抽象类
public abstract void 方法名() ; // 抽象方法,只声明而未实现
}

5.3不能被实例化

在抽象类的使用中有几个原则:
· 抽象类本身是不能直接进行实例化操作的,即:不能直接使用关键字new完成。
· 一个抽象类必须被子类所继承,被继承的子类(如果不是抽象类)则必须覆写(重写)抽象类中的全 部抽象方法。

5.4常见问题

1、 抽象类能否使用final声明?
不能,因为final属修饰的类是不能有子类的 , 而抽象类必须有子类才有意义,所以不能。
2、 抽象类能否有构造方法?
能有构造方法,而且子类对象实例化的时候的流程与普通类的继承是一样的,都是要先调用父类中的 构造方法(默认是无参的),之后再调用子类自己的构造方法。

5.5抽象类和普通类的区别

1、抽象类必须用public或procted 修饰(如果为private修饰,那么子类则无法继承,也就无法实现其 抽象方法)。默认缺省为 public
2、抽象类不可以使用new关键字创建对象, 但是在子类创建对象时, 抽象父类也会被JVM实例化。
3、如果一个子类继承抽象类,那么必须实现其所有的抽象方法。如果有未实现的抽象方法,那么子类也必 须定义为 abstract类

6.接口

6.1概念:

如果一个类中的全部方法都是抽象方法,全部属性都是全局常量,那么此时就可以将这个类定义成一个接口。
定义格式:
interface 接口名称{
全局常量 ;
抽象方法 ;
}

6.2接口可以多实现:

格式:
class 子类 implements 父接口1,父接口2…{
}

以上的代码称为接口的实现。那么如果一个类即要实现接口,又要继承抽象类的话,则按照以下的格式编写即可:
class 子类 extends 父类 implements 父接口1,父接口2…{
}

7.Object类

7.1概念

Object类是所有类的父类(基类),如果一个类没有明确的继承某一个具体的类,则将默认继承Object类。
例如我们定义一个类:
public class Person{
}
其实它被使用时 是这样的:
public class Person extends Object{
}

7.2toString

建议重写Object中的toString方法。 此方法的作用:返回对象的字符串表示形式。
Object的toString方法, 返回对象的内存地址

7.3equals

建议重写Object中的equals(Object obj)方法,此方法的作用:指示某个其他对象是否“等于”此对象。
Object的equals方法:实现了对象上最具区别的可能等价关系; 也就是说,对于任何非空引用值x和y ,当且仅当x和y引用同一对象( x == y具有值true )时,此方法返回true 。
equals方法重写时的五个特性:
自反性 :对于任何非空的参考值x ,x.equals(x)应该返回true 。
对称性 :对于任何非空引用值x和y ,x.equals(y)应该返回true当且仅当y.equals(x)回报true 。
传递性 :对于任何非空引用值x , y和z ,如果x.equals(y)回报true个y.equals(z)回报true,然后x.equals(z)应该返回true 。
一致性 :对于任何非空引用值x和y ,多次调用x.equals(y)始终返回true或始终返回false ,前 提是未修改对象上的equals比较中使用的信息。
非空性 :对于任何非空的参考值x , x.equals(null)应该返回false 。

8.包装类

Java面向对象_第2张图片

8.1字符串转换

使用包装类还有一个很优秀的地方在于:可以将一个字符串变为指定的基本数据类型,此点一般在接收输入数据上使用较多。
在Integer类中提供了以下的操作方法:
public static int parseInt(String s) :将String变为int型数据
在Float类中提供了以下的操作方法:
public static float parseFloat(String s) :将String变为Float
在Boolean 类中提供了以下操作方法:
public static boolean parseBoolean(String s) :将String变为boolean

9.多态

9.1概念

多态: 就是对象的多种表现形式,(多种体现形态)

9.2多态的体现

对象的多态性,从概念上非常好理解,在类中有子类和父类之分,子类就是父类的一种形态 ,对象多态性就从此而来。
ps: 方法的重载 和 重写 也是多态的一种, 不过是方法的多态(相同方法名的多种形态)。
重载: 一个类中方法的多态性体现
重写: 子父类中方法的多态性体现。

9.3多态的使用:对象的类型转换

类似于基本数据类型的转换:

· 向上转型:将子类实例变为父类实例
|- 格式:父类 父类对象 = 子类实例 ;
· 向下转型:将父类实例变为子类实例
|- 格式:子类 子类对象 = (子类)父类实例 ;

最后放上一个练习

试题:设置一个类,命名为MyList
 	类中包含属性:Object[]element
 	方法有如下几个: 
 	1.增加方法add:可以向数组属性中依次存储Object,数组内容 存满时,需实现动态扩容(详解在下面)。 
 	2.删除方法remove:可以根据数据或下标,从数组属性中删除 Object数据,删除后,数组后续元素需前移。 
 	3.查询方法get:方法传入下标,返回数组中指定下标的数据。 当前存储数据量size:获取当前存储的有效数据长度 
 	动态扩容详解:无需真正增加原数组的容量,只用将原内容复制到新 的大数组,然后让原数组名称重新等于大数组即可。由于原数组数据在堆中,失去引用会被GC自动回收。

我的实现如下:

public class MyList {
     
    Object[] element = new Object[5];
    //当前存储数据量
    static int size = 0;

    //增加方法add:可以向数组属性中依次存储Object,数组内容 存满时,实现动态扩容。
    public void add(Object o) {
     
        element[size] = o;
        size++;

        //动态扩容
        if (element.length == size + 1) {
     
            Object[] test = new Object[size + 6];
            for (int i = 0;i < element.length;i++) {
     
                test[i] = element[i];
            }
            element = test;
            System.out.println("扩容完成!总容量更改为:" + element.length);
        }
    }
    //删除方法remove:可以根据下标,从数组属性中删除 Object数据,删除后,数组后续元素需前移。
    public void remove(int a) {
     
        if (a > size) {
     
            System.out.println("长度错误!");
            return;
        }
        for (int i = a;i < element.length - 1;i++) {
     
            element[i] = element[i + 1];
        }
        System.out.println("删除成功!");
        size--;
        for (int i = 0; i < size; i++) {
     
            System.out.print(element[i] + "\t");
        }
        System.out.println();
    }

    //方法重载,删除方法remove:可以根据数据,从数组属性中删除 Object数据,删除后,数组后续元素需前移。
    public void remove(Object o) {
     
        int i;
        //-1表示没有找到,不然会被赋值为找到的数据的下标
        int flat = -1;
        for (i = 0;i < size;i++) {
     
            if (this.element[i].equals(o)) {
     
                flat = i;
                break;
            }
        }
        if (flat != -1){
     
            remove(i);
        }else {
     
            System.out.println("数据不存在!");
        }
    }

    //查询方法get:方法传入下标,返回数组中指定下标的数据。 当前存储数据量size:获取当前存储的有效数据长度
    public Object get(int a) {
     
        if (a >= 0 && a < size)
        return element[a];
        return "下标不正确!";
    }
}

测试类:

public class MyListTest {
     
    public static void main(String[] args) {
     
        MyList my = new MyList();
        my.add("何世鹏");
        my.add("2");
        my.add("3");
        my.add("4");
        my.add("5");
        Integer a = new Integer(10);
        Integer b = 996;
        my.add(b);
        my.add("7");
        my.add("8");
        my.add("9");
        my.add(a);

        //测试下标超出范围的情况
        my.remove(30);
        //测试数据错误的情况
        my.remove("1024");
        //测试找到数据的情况
        my.remove("何世鹏");

        //测试返回给定下标对应的值
        System.out.println(my.get(2));
        //下标不正确
        System.out.println(my.get(9));


    }
}

测试结果:
Java面向对象_第3张图片

你可能感兴趣的:(笔记,java)