面向对象的基础篇_01

版权声明:本文为博主原创文章,未经博主允许不得转载。多多评论,与博主一起学习编程。 https://blog.csdn.net/Roobert_Chao/article/details/78569921

基础篇_01的主要内容

  • 1、 面向对象的基本概念
  • 2、 类与对象的关系、引用传递
  • 3、 类封装性的操作
  • 4、 构造方法的定义及使用
  • 5、 匿名对象(重点)
  • 6、 String 类的使用
  • 7、 this 关键字的作用

一丶面向对象的简单了解

面向对象是针对于一类问题来进行解决,某一局部的修改不影响其他位置的变化。

  • 在面向对象中主要分为以下三个方面:
    • OOA:面向对象分析。
    • OOD:面向对象设计,根据分析的结果使用工具完成设计。
    • OOP:完成具体的功能实现,代码编写。
  • 在面向对象中,实际上还存在着三个主要的特性:
    • 封装性:private属性+public方法。
    • 继承性:子类和父类之间的继承,方法的重写+属性的改变;
    • 多态性:有继承+重写+父类引用指向子类对象

可以参考:java面向对象的三大特性

二丶类与对象的关系

  • 类是对象的模板,对象是类的实例
    • 类:类是一组共性的产物,是同一类事物的集中表现。
    • 对象:是一种个性的体现,是个体的产物。
    • 对象中的所有操作行为都由类决定,所以,在使用中只要是类定义出的操作对象都可以应用,而如果类没有定义出的操作,对象肯定无法使用。

1丶类和对象

①在 Java 中可以使用 class 关键字来定义一个类,在类中有两大组成部分:属性(变量)、方法。
一个类定义完成之后肯定无法直接使用,需要依靠对象进行操作,这就是对象的实例化。

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

一旦将对象实例化之后呢,可以通过“对象名称.属性()”和“对象名称.方法()”进行类的调用。

举例:
class Person{  // 定义类
    String name ;  // 表示一个人的姓名
    int age ;  // 表示一个人的年龄
    public void tell(){  // 表示一个功能,说话
        System.out.println("姓名:" + name + ",年龄:" + age) ;
    }
};
public class Demo01{
    public static void main(String args[]){
        Person per = new Person() ; // 产生对象
        per.name = "张三" ;  // 设置 name 属性的内容
        per.age = 30 ;  // 设置 age 属性的内容
        per.tell() ; // 调用方法输出
    }
};
  • 对象产生:Person per = new Person() ;

既然存在了关键字 new,而且类又属于引用数据类型,那么肯定现在
就开辟了相应的栈及堆内存空间,而且以上的代码可以拆分成两步:

  • |- 声明对象:Person per = null ; --> 在栈内存中声明
  • |-实例化对象:per = new Person() ; --> 开辟对应的堆内存空间

|-1、栈内存是存储变量的名称的。per作为变量名称存储在栈内存中。
|-2、new 了一个类名称之后,开始在堆内存中为这个类分配内存空间。
|-3、声明对象后的per就好比一个空的指针,在实例化对象之后,per指向了堆内存中person类中的属性,可以通过per.name="houzi"和per.age="3"对属性进行赋值,还可以通过per.tell();调用方法。

需要注意的是:

**※ 每一个对象拥有各自的内存空间,不会互相影响。
**※ 每一个对象中实际上保存的只是属性,并没有保存方法,因为所有的方法都是每个对象所共同拥有的,保存在 全局代码区 之中。
**※ 栈内存保存的是对堆内存的引用地址,栈内存-->堆内存,而堆内存中保存的是每一个对象所拥有的属性,而 全局代码区 之中保存的是所有类中的方法,表示公共调用。

2丶引用传递

+++引用到了上述的代码+++

  • 引用传递指的就是一个堆内存空间,可以同时被多个栈内存所指向

**简单理解:就是在声明对象的时候,在栈内存声明了两个对象名称,并且同时指向了同一个实例化对象实例化的对象在堆内存中开辟的空间是一个

声明两个对象,栈内存中的两个空间存放
本人理解为存放的是指针,只具有指向作用

Person per1 = null ;
Person per2 = null ;

这里两个对象的 指针 指向同一个堆内存中开辟的Person空间

per1 = new Person(); 
per2 = new Person(); 

举例:

public class Demo02 {
    public static void main(String args[]){
        Person per1 = null ;
        per1 = new Person() ; // 实例化
        Person per2 = null ;
        per2 = new Person() ; // 实例化
        //赋值操作
        per1.name = "张三" ;
        per1.age = 30 ;
        per2.name = "李四" ;
        per2.age = 20 ;
        /*
         *per2指向了per1的堆内存中保存per1访问属性的空间,
         *造成per2原有数据丢失,访问的是与per1相同的属性。
         */
        per2 = per1 ;
        per2.tell() ;
    }
};

三丶类封装性的操作

封装性就是指类内部的定义对外部不可见。

  • 属性或方法不希望被外部用 所访问的话,则可以使用 private 关键字声明。

1丶在 JAVA开发的标准规定中,只要是属性封装,则设置取得就要依靠setter[进行内容的设置] 及 getter[取得] 方法完成操作。

【代码编辑界面右击】-->【source】-->【generate getter and setter】

<->只要是属性就必须进行封装,封装之后的属性必须通过setter和getter设置和取得。<->
<-->强调:在一个类中所有的方法是允许互相调用的,如果非要强调是本类中的方法的话,则在调用的方法前增加一个“this”关键字,表示的是本类中的方法。<-->

四丶构造方法的定义及使用

  • Person per = new Person() ;
    Person()就表示的是一个构造方法,此构造方法属于默认的构造方法。

构造方法的定义:在一个类中定义的方法名称与类名称相同,且无返回值声明的方法。在一个类中如果没有明确的定义一个构造方法的话,则会自动生成一个无参的,空的构造方法。

  • 一个类永远都会保存至少有一个构造方法。构造方法可以重载。

方法重载:方法名称相同,参数的类型或个数不同。*

所有的构造方法是在对象使用关键字 new 进行实例化的时候调用的,而且每次使用关键字 new 开辟新的堆内存空间时,构造方法都要被调用。实际上构造方法的主要作用就是为一个类中的属性 初始化 的。

五丶匿名对象(重点)

匿名对象就是表示没有名字的对象。

  • 匿名对象没有对应的栈内存所指向,所以使用一次之后就等待被垃圾回收了。
class Person{  // 定义类
    private String name ; // 表示一个人的姓名
    private int age ; // 表示一个人的年龄
    public Person(String n,int a){// 通过构造方法为属性自动初始化
        this.setName(n) ;
        this.setAge(a) ;
    }
    public void setName(String n){  // 设置姓名
        name = n ;
    }
    public void setAge(int a){  // 设置年龄
        if(a>=0 && a<=150){ // 合法年龄
        age = a ;
        }
    }
    public String getName(){  // 取得姓名
        return name ;
    }
    public int getAge(){  // 取得年龄
        return age ;
    }
    public void tell(){  // 表示一个功能,说话
        System.out.println("姓名:" + this.getName() + ",年龄:" + this.getAge()) ;
    }
};
public class Demo03 {
    public static void main(String args[]){
        new Person("张三",30).tell() ;
    }
};

通过设置一个含参数的构造方法,进行匿名对象的调用。

匿名与非匿名的差别:

  • 在内存中的分布不同:匿名对象创建的对象只存在于堆中;非匿名对象创建对象时的对象虽然也在堆中,但其类变量却在栈中,栈中的类变量通过创建变量的内存地址来指向相应的对象。
  • 从调用意义来看
    • ①匿名对象调用方法有意义,而调用类中的属性则没有意义。例如:

      new Student().name="wangwu";

      这属于使用匿名对象调用属性。这种调用没有意义,当代码执行到这一行代码时则修改new Student()对象的name属性,可是当该条语句被执行后呢?由于这时new Student()没有继续引用,所以此对象在堆中就成了垃圾。
      匿名对象调用方法有意义,方法存在于栈空间,当在内存中创建的对象调用方法时,JVM开始为局部变量开辟内存空间,方法开始执行,方法强调其功能,对象调用方法可以完成其功能,所以匿名对象调用方法有意义。
    • ②非匿名对象调用方法或调用类中的属性都有意义(其中前者不在累述,请参见第①点)。例如:
      Student stu=new Student();
      stu.name=”wangwu”
      -这属于使用非匿名对象调用属性。当代码执行到这一行代码时则修改stu对象的那么属性,此时使用该对象调用print()方法则输出的name值为wangwu,鉴于这一点所以认为非匿名对象调用属性实用意义的。

六丶String 类的使用

1、String 类的对象实例化

String 在使用中有两种实例化的方法。

  • 一种是采用直接赋值(将字符串赋 String 的对象)
    • String str = “Hello” ;
  • 第二种方法是通过构造方法完成实例化的操作
    • String str = new String(“Hello”) ;

2、字 符串 的 比较 ( 重 点)

  • “==” 用在数值上表示判断是否相等 ,如果是用在了对象上,则表示的是判断两个对象的地址是否相等。
    • str1==str2
  • equals():用于内容的比较,比较两个字符串的内容是否相等
    • str1.equals(str2))

3、一个字 符串个 就是一个 String 的 的 匿 名对象

  • 一个字符串就是 String 类的匿名对象可以直接使用。
    通过一个例子证明
public class Demo04 {
    public static void main(String args[]){
        System.out.println("hello".equals("hello")) ; // true
    }
};

通过Demo04程序可以清楚的验证,之前使用直接赋值的方式为 String 类进行实例化的操作,就属于将一个匿名对象起了一个名字。

4、两种实例化的比较

  • String str = "TheString";
    • 这样写的代码,只在堆内存中开辟了一块空间。
  • String str = new String("Hello") ;
    • 由于内部的字符串属于匿名对象,字符”Hello”在堆内存中会有占有一个空间的位置,实例化new的时候会重新开辟一个空间来存放字符”Hello”,原有的字符串Hello的空间将变为垃圾。
    • JAVA底层中存在了一个字符串的对象池,每次的内容都会从池中取出,如果内容已经存在了,则使用已经存在的,如果不存在,则会生成一个新的,放入池中,属于 共享设计模式

5、字符串的内容一旦声明则不可改变

public class StringDemo {
    public static void main(String args[]){
        String str = "hello" ;
        str = str + " world" ;
        str += " !!!" ;
        System.out.println(str) ;
    }
};

每一个字符串的内容原本并没有发生任何的改变,改变的是只一个字符串的内存地址的指向,而且操作完成之后会发现有很多的垃圾产生。

6、String 类的相关操作( 类的相关操作( 重点)

在实际的开发中,String 类的使用是最频繁的,而且在 String 类中提供了大量的操作方法。

①字符串与字符数组
  • 字符串和字符数组的转换
  • 取出指定位置的字符
public class StringDemo01 {
    public static void main(String args[]){
        String str = "helloworld" ;
        System.out.println(str.charAt(0)) ;//取出第一个字符
        System.out.println(str.charAt(3)) ;//取出第三个字符

        System.out.println("字符串的长度是:" + str.length()) ;//获得字符数组长度

        char c[] = str.toCharArray() ; // 将字符串变为字符数组
        for(int x=0;x<c.length;x++){//c.length是字符数组的长度
            System.out.print(c[x] + "、") ;
        }

        System.out.println("\n" + new String(c)) ;
        //把字符数组c变为字符串。
        System.out.println(new String(c,0,5)) ;//把指定位置的字符数组变为字符串
    }
};
②字符串与字节数组

一般在以后进行 IO 操作的时候往往会使用到字节数组的功能

  • 将字符串变为字节数组
  • 将指定范围的字节数组变为字符串
public class StringDemo02{
    public static void main(String args[]){
        String str = "helloworld" ;
        byte b[] = str.getBytes() ;  // 将字符串变为字节数组
        System.out.println(new String(b)) ;
        System.out.println(new String(b,0,5)) ;
        //将指定范围的字节数组变为字符串
    }
};
③字符串的比较、截取、存在、拆分、替换及其他操作

比较
- equals("HELLO") 考虑大小写的比较
- equalsIgnoreCase(String anotherString)忽略大小写的比较

public class StringDemo03 {
    public static void main(String args[]){
        String str = "hello" ;
        System.out.println(str.equals("HELLO")) ;
        //区分大小写的比较
        System.out.println(str.equalsIgnoreCase("HELLO")) ;//忽略大小写的比较
    }
};

截取
- substring(int beginIndex)从指定位置截取到末尾
- substring(int beginIndex,int endIndex)截取指定范围的内容

public class StringDemo04 {
    public static void main(String args[]){
        String str = "helloworld" ;
        System.out.println(str.substring(5)) ;
        //从第六个字符开始截取到最后
        System.out.println(str.substring(0,5)) ;
        //从一开始截取到第六个字符
    }
};

存在
- indexOf(String str)从头开始判断,如果找到则返回位置的数值,找不到返回值-1
- indexOf(String str,int fromIndex)从指定位置开始查找,如果找到则返回位置,找不到返回-1
- contains(String s)直接判断是否存在

  • 一般而言已经开发施加较长的人员都会使用 indexOf()进行判断,通过判断其是否是-1,来决定是否有内容。
public class StringDemo05 {
    public static void main(String args[]){
        String str = "helloworld" ;
        if(str.indexOf("hello") != -1){
            System.out.println("已经查找到了内容,位置是:" + str.indexOf("hello")) ;
        }
    }
};

拆分
-split(String regex)按照指定字符串拆分

  • 在进行字符串拆分的时候,如果发现有某些字符串无法拆分,则使用转义字符"/"。
public class StringDemo06 {
    public static void main(String args[]){
        String str = "hello world !!!" ;
        String s[] = str.split(" ") ;
        //这里表示遇到空格变拆分字符串
        for(int x=0;x<s.length;x++){
            System.out.print(s[x] + "、") ;
        }
    }
};

替换
-replaceAll(String regex,String replacement)全部替换。
-replaceFirst(String regex,String replacement)替换第一个满足的内容。

public class StringDemo07 {
    public static void main(String args[]){
    String str = "helloworld" ;
    System.out.println(str.replaceAll("l","⊙")) ;
    System.out.println(str.replaceFirst("l","⊙")) ;
    }
};

其他操作
public String toLowerCase()转小写。
public String toUpperCase()转大写。
public String trim()去掉左右空格。
public boolean startsWith(String prefix)判断是否以指定的字符串开头。
public boolean endsWith(String suffix)判断是否以指定的字符串结尾。

public class StringDemo08 {
    public static void main(String args[]){
    String str = "  helloworld  ".trim() ;
    //去掉左右空格。
    System.out.println(str) ;
    System.out.println(str.toUpperCase()) ;
    //转大写。
    System.out.println(str.startsWith("hello")) ;
    //判断是否以指定的字符串开头。
    System.out.println(str.endsWith("d")) ;
    //判断是否以指定的字符串结尾。`
    }
};

7、对象数组:就是一组对象

  • 类名称 对象数组名称 [] = new 类名称[对象数组长度] ;
  • 类是引用数据类型,所以对象数组中的每一个内容都是 null,在使用的时候肯定是需要进行分别实例化的。
Person per[] = {new Person("张三",10),
new Person("李四",20),new Person("王五",30)} ;
Person per[] = new Person[3] ;  // 开辟三个大小的对象数组
    per[0] = new Person("张三",10) ;
    per[1] = new Person("李四",20) ;
    per[2] = new Person("王五",30) ;

七丶this关键字

  • 访问属性
  • 调用方法(包含了构造)
  • 表示当前对象
  • 1) this 关键字是类内部当中对自己的一个引用,可以方便类中方法访问自己的属性;
    2)可以返回对象的自己这个类的引用,同时还可以在一个构造函数当中调用另一个构造函数。

1、访问属性

public Person(String name,int age){
    this.name = name ;
    this.age = age ;
}
  • 把构造方法中的 name 或 age 参数给类中的 name 和 age 属性的话,就需要通过 this 来表示出本类的属性。
    • this.name 是访问本类中的属性。后边的name是含参数构造器中的参数。

2、调用方法

|- 如果使用 this 调用本类中其他构造方法的话,则此语句必须放在构造方法的首行。
|-一个类中如果有多个构造方法的话,则肯定保留有一个是不用this ” 调用其他构造的情况,以作为出口
|- 将参数少的构造方法放在最前面,参数多的构造方法放在最后面。

this() ;  // 调用本类中的无参构造
this(name) ;  // 调用有一个参数的构造

3、表示当前

通常在set方法和构造函数中都会使用, 当局部变量和成员变量同名时访问成员变量(因为成员变量会被局部变量覆盖)

猜你喜欢

转载自blog.csdn.net/Roobert_Chao/article/details/78569921