java基础-类和对象的基本概念学习

1、面向对象与面向过程

面向过程

一种较早的编程思想,顾名思义就是该思想是站着过程的角度思考问题,强调的就是功能行为,功能的执行过程,即先后顺序,而每一个功能我们都使用函数(类似于方法)把这些步骤一步一步实现。使用的时候依次调用函数就可以了。(效率高)

面向对象

一种基于面向过程的新编程思想,顾名思义就是该思想是站在对象的角度思考问题,我们把多个功能合理放到不同对象里,强调的是具备某些功能的对象。(易扩展,低耦合)

引入例子:

先用面向过程的方式来写(c语言版)

#include <stdio.h> 
#include <math.h>
#include <stdbool.h> 
void printMenuAndPrice(); 
int selectMenu(); 
int countPrice(int code);
bool pay(int code);
int main() { 
    //打印菜单和价格 
    printMenuAndPrice();
    //选中想要购买的菜 
    int code = selectMenu();
    //计算价格
    countPrice(code);
    //⽀付
    if (pay(code)){
        //逻辑代码 
    }
    return 0;
}
void printMenuAndPrice(){
    //打印菜单 
}
int selectMenu(){ 
    //⽤⼾选择,返回⼀个代号,或者数组等其他⽅式
    return 0;
}
int countPrice(int code){
    //根据代号,计算价格 
    return 0;
}
bool pay(int code){
    //⽀付⽅式,判断⽀付是否成功
    return false;
}

感觉也能实现。但是如果很多过程,⽐如⼀个app,有很多逻辑要写,不可能像这样全是全局变量。就很不⽅便管理和处理bug。⽽Java⾯向对象,就可以⽤⽅法处理对象数据,相对于我们更⽅便。(当然c语⾔在其他⽅⾯也是很强⼤的)

那用面向对象实现怎么实现呢?

public class Main { 
    public static void main(String[] args) { 
        //先实例化⼀个⻝堂对象 
        Canteen honggaoliangCanteen = new Canteen(); 
        //名字设为红⾼粱 
        honggaoliangCanteen.setCanteenName("莘莘学子");
        //实例化⼀个学⽣顾客 
        StudentCustomer studentHljj = new StudentCustomer(10, 20);
        //⻝堂展⽰菜单 
        honggaoliangCanteen.showMenu();
        //学⽣点餐
        Food noodle = studentHljj.order("重庆⼩⾯", 10); 			    
        //付款
        //⽤卡⾥的钱
        studentHljj.payByCard(noodle.getPrice());
        //或者直接给钱 
        studentHljj.pay(noodle.getPrice()); 
        //判断支付是否成功 
    }
}

其中,对象中编写了对应的方法,我们需要什么方法,就用相应的对象去调用相应的方法就可以了。

2、类与对象

2.1、类

类是一个模板,是一个抽象性概念,它描述一类对象的行为和状态。

构建类的语法

class 类名称{
    属性
	方法
	构造方法
}

其中根据在变量(属性)在类中声明的位置分为成员变量和局部变量和静态变量

成员变量

定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。成员变量前可以放修饰符。
有效范围:成员变量在整个类中都有效,习惯性先写属性再写方法。

局部变量

在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。局部变量前不能放置任何访问修饰符 (private,public和protected)。
有效范围:只在方法内有效,而且与声明的位置有关。方法的参数在整个方法中有效,方法内部的局部变量从声明它的位置之后有效。如果局部变量在一个复合语句中,那么仅仅在复合语句中有效

静态变量

静态变量也声明在类中,方法体之外。但必须声明为static类型.静态变量是所有对象共有,其中一个对象将它值改变,其他对象得到的就是改变后的结果;而成员变量则属对象私有,某一个对象将其值改变,不影响其他对象;

成员变量和局部变量区别
  • 如果成员变量在声明的没有指定初始值,所使用的构造方法也没有对成员变量进行初始化操作,那么对于整型变量,默认初始值为0;对于浮点型,默认值为0.0;对于boolean型,默认值为false;对于引用型(除了那八大基本类型),默认值为null。

  • 成员变量还有默认值,局部变量没有默认值,因此在使用局部变量的时候,必须保证局部变量有具体的值。

  • 就近原则: 如果局部变量的名字和成员变量的名字相同,那么成员变量会被隐藏,即该成员变量在这个方法内部暂时失效。如果想使用被隐藏了的成员变量,必须使用关键字this。
    例子:

    	public class Tom {
        	int x=10; 
            int y1,y2;
       	 void f(){
         	   int x=5;
           	 	y1=x+x; 
             	y2=x+this.x;
            	System.out.println("y1的值为:"+y1+"y2的值为:"+y2);
       	 }
    

实例方法

当一个类创建了一个对象后,这个对象就可以调用该类的方法(对象方法)。

1.实例方法中可以用对象变量,也可以用静态变量;

2.实例方法中可以调用静态方法,也可以调用非静态的方法;

3.方法中可以使用super,this关键字。

静态方法

用static修饰的方法。

由于类方法是属于整个类的,并不属于哪个个对象,所以类方法的方法体中不能有与类的对象有关的内容。即类方法体有如下限制:

1.静态方法中不能引用非静态变量,只能访问静态变量和静态方法.而实例方法可以访问静态的.

2.静态方法中不能调用类的非静态方法;

3.在静态方法中不能调使用super,this关键字;

4.静态方法不能被覆盖

实例和静态方法两者区别

当类的字节码文件被加载到内存时,类的实例方法不会被分配入口地址,当该类创建对象后,类中的实例方法才分配入口地址,从而实例方法可以被类创建的任何对象调用执行。需要注意的是,当我们创建第一个对象时,类中的实例方法就分配了入口地址,当再创建对象时,不再分配入口地址,也就是说,方法的入口地址被所有的对象共享,当所有的对象都不存在时,方法的入口地址才被取消。

对于类中的类方法,在该类被加载到内存时,就分配了相应的入口地址。从而类方法不仅可以被类创建的任何对象调用执行,也可以直接通过类名调用。类方法的入口地址直到程序退出时才被取消。

类方法在类的字节码加载到内存时就分配了入口地址。因此,Java语言允许通过类名直接调用类方法,而实例方法不能通过类名调用。在Java语言中,类中的类方法不可以操作实例变量,也不可以调用实例方法,这是因为在类创建对象之前,实例成员变量还没有分配内存,而且实例方法也没有入口地址。

构造方法

构造器不能定义返回值类型声明,也不能使用void定义构造器没有返回值。如果为构造器定义了返回值类型,或使用void定义构造器没有返回值,编译时不会出错,但Java会把这个所谓的构造器当成普通方法来处理。

构造函数与普通函数的区别
  1. 一般函数是用于定义对象应该具备的功能。而构造函数定义的是,对象在调用功能之前,在建立时,应该具备的一些内容。也就是对象的初始化内容。
  2. 普通函数可以使用对象多次调用,构造函数就在创建对象时调用。
  3. 构造函数的函数名要与类名一样,而普通的函数只要符合标识符的命名规则即可。
  4. 构造函数没有返回值类型。

注意的细节:
(1).在一个类中可以定义多个构造函数,以进行不同的初始化。多个构造函数存在于类中,是以重载的形式体现的。因为构造函数的名称都相同。
(2).构造函数可以调用另一个构造函数,语法:this(参数),必须在方法的第一句就进行调用。

注意

对成员变量的操作只能放在方法中,方法中可以使用各种语句对成员变量和方法体中声明的局部变量进行操作,但是,我们可以在声明成员变量的时候就进行赋值操作。int i =9;
但是不可以这样做:

class A {
	int a;
	a=12;//语句不是变量的声明,只能出现在方法体中
}

主函数:是一个特殊的函数。作为程序的入口,可以被JVM调用
固定语法public static void main(String[] args) {..... }

2.2、对象

对象是类的一个实例。所谓对象就是真实世界中的实体,也就是说现实世界中每一个实体都是一个对象,它是一种具体的概念

区别:类是对象的模板,对象是类的实例。类一般只有通过对象才可以使用,而在开发之中应该先产生类,之后再产生对象。类通常不能直接使用,对象是可以直接使用的。

例如:王者荣耀中战士就是一个类,里面的典韦就是一个对象,然后典韦的攻击力,生命上限这些都是他的属性。

接下来,我们就来学习如何创建类。

创建对象:

通常情况下一个类不能直接使用,需要根据类创建一个对象,才能使用。

我们使用关键字new来创建一个新的对象,创建对象需要以下三步:

  1. 声明:声明一个对象,包括对象名称和对象类型

  2. 实例化:使用关键字new来创建一个对象

  3. 初始化:使用new创建对象时,会调用构建方法初始化对象

    下面是一个创建对象的例子:

    语句:类名称 对象名称 = new 类名称();

    public class Test{
        public Test(){
            System.out.println("对象创建了");
        }
        public static void main(String[] args){
            //下面的语句将创建一个对象
            Test test = new Test();
            //也可以这样创建
            Test test1;
            test1 = new Test();
        }
    }
    

    我们可以通过已经创建的对象来访问成员变量和方法

    对象名.成员变量名称

    对象名称.成员方法名称

    对象的内存模型

    1).当我们声明对象后,该对象还只是一个空对象,还不能使用。因为它还没有得到任何的“实体”,必须为该空对象进行分配变量。
    2)new运算符和构造方法会为我们空对象进行赋值操作:
    3).先为里面的成员变量分配内存,然后再执行构造方法中的语句,如果成员变量在声明时没有指定初始值,所使用的构造方法中也没有对成员变量进行初始化操作,那么这些变量会是默认初始值。
    4).new运算符在为成员变量分配内存后,将计算出一个引用(地址值),把该值赋值给我们声明的空对象。所以我们声明的对象中保存的是个地址值,该地址指向实际的存储的值。
    5).一个类通过使用new可以创建多个不同的对象,这些对象将被分配不同的内存空间。

    注意

    注意:空对象不能使用,假如程序中使用了空对象,程序会在运行时出现NullPointerException异常。

    当我们使用new关键字创建两个对象后,这两个对象所指向的内存地址不是同一块,所以,这两个对象是不同的对象。如Dog dog1 = new Dog(); Dog dog2 = new Dog(); 但是,当我们进行赋值操作后,即dog1=dog2后,我们就把dog2所指向的地址交给了dog1进行管理,这个时候,dog1dog2都管理的是同一块地址。这个时候,可以说dog1dog2是相同对象了。这时候,因为原来dog2指向的内存空间已经不再被任何对象所拥有,所以java的“垃圾收集”机制会释放dog2原来执行的内存地址。

    如果我们要进行对象内容的比较,如果这两个对象的内容相等,那么就判断这两个对象是同一个的话,我们要自己重写equal方法。

    源文件声明规则

    当在一个源文件中定义多个类,并且还有import语句和package语句时,要特别注意这些规则。

    • 一个源文件中只能有一个 public 类
    • 一个源文件可以有多个非 public 类
    • 源文件的名称应该和 public 类的类名保持一致。例如:源文件中 public 类的类名是 Employee,那么源文件应该命名为Employee.java
    • 如果一个类定义在某个包中,那么 package 语句应该在源文件的首行。
  • 如果源文件包含 import 语句,那么应该放在 package 语句和类定义之间。如果没有 package 语句,那么 import 语句应该在源文件中最前面。

    • import 语句和 package 语句对源文件中定义的所有类都有效。在同一源文件中,不能给不同的类不同的包声明。

    类有若干种访问级别,并且类也分不同的类型:抽象类和 final 类等。这些将在下一节课讲到。

    除了上面提到的几种类型,Java 还有一些特殊的类,如:内部类匿名类

    这两种特殊的类大家可以自行下去了解.

  1. 封装

在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。

封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。

要访问该类的代码和数据,必须通过严格的接口控制。

封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。

适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。

封装的优点

  • 良好的封装能够减少耦合。
    • 类内部的结构可以自由修改
    • 可以对成员变量进行更精确的控制。
    • 隐藏信息,实现细节。

实现封装的步骤

  1. 修改属性的可见性来限制对属性的访问(一般限制为private)

  2. 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问

    实例:

public class EncapTest{
 
   private String name;
   private String idNum;
   private int age;
 
   public int getAge(){
      return age;
   }
 
   public String getName(){
      return name;
   }
 
   public String getIdNum(){
      return idNum;
   }
 
   public void setAge( int newAge){
      age = newAge;
   }
 
   public void setName(String newName){
      name = newName;
   }
 
   public void setIdNum( String newId){
      idNum = newId;
   }
}

以上实例中public方法是外部类访问该类成员变量的入口。

通常情况下,这些方法被称为getter和setter方法。

因此,任何要访问类中私有成员变量的类都要通过这些getter和setter方法。

通过如下的例子说明EncapTest类的变量怎样被访问:

public class RunEncap{
   public static void main(String args[]){
      EncapTest encap = new EncapTest();
      encap.setName("James");
      encap.setAge(20);
      encap.setIdNum("12343ms");
 
      System.out.print("Name : " + encap.getName()+ 
                             " Age : "+ encap.getAge());
    }
}

修饰符

修饰符用来定义类、方法或者变量,通常放在语句的最前端。

主要分为以下两种

访问修饰符

java支持4种不同的访问权限

  • default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。

  • private : 在同一类内可见。使用对象:变量、方法。注意:不能修饰类

  • public : 对所有类可见。使用对象:类、接口、变量、方法

  • protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。

  • 修饰符当前类同一包内子孙类(同一包)子孙类(不同包)其他包
    publicYYYYY
    protectedYYYY/N(说明N

| default | Y | Y | Y | N | N |
| private | Y | N | N | N | N |

默认访问修饰符

不使用任何关键字

使用默认访问修饰符声明的变量和方法,对同一个包内的类是可见的。接口里的变量都隐式声明为 public static final,而接口里的方法默认情况下访问权限为 public

私有访问修饰符-private

私有访问修饰符是最严格的访问级别,所以被声明为 private 的方法、变量和构造方法只能被所属类访问,并且类和接口不能声明为 private。声明为私有访问类型的变量只能通过类中公共的 getter 方法被外部类访问。Private 访问修饰符的使用主要用来隐藏类的实现细节和保护类的数据。

下面是一个例子:

 public class Logger {
    private String format;
    public String getFormat() {
       return this.format;
    }
    public void setFormat(String format) {
       this.format = format;
    }
}

实例中,Logger 类中的 format 变量为私有变量,所以其他类不能直接得到和设置该变量的值。为了使其他类能够操作该变量,定义了两个 public 方法:getFormat()(返回 format的值)和 setFormat(String)(设置 format 的值)

公有访问修饰符-public

被声明为 public 的类、方法、构造方法和接口能够被任何其他类访问。如果几个相互访问的 public 类分布在不同的包中,则需要导入相应 public 类所在的包。由于类的继承性,类所有的公有方法和变量都能被其子类继承。

受保护的访问修饰符-protected

protected 需要从以下两个点来分析说明:

子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问;

子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法。

protected 可以修饰数据成员,构造方法,方法成员,不能修饰类(内部类除外)。接口及接口的成员变量和成员方法不能声明为 protected。

非访问修饰符

为了实现一些其他的功能,Java 也提供了许多非访问修饰符。

static 修饰符,用来修饰类方法和类变量。

final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。

abstract 修饰符,用来创建抽象类和抽象方法。

synchronized 和 volatile 修饰符,主要用于线程的编程。

3、java 的包(package)

  • 包主要用来对类和接口进行分类。当开发 Java 程序时,可能编写成百上千的类,因此很有必要对类和接口进行分类。

  • 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。

  • 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。

  • 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

    Java 使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等。

    包语句的语法格式为:

    package pkg1[.pkg2[.pkg3…]];

    包声明应该在源文件的第一行,每个源文件只能有一个包声明,这个文件中的每个类型都应用于它。

    如果一个源文件中没有使用包声明,那么其中的类,函数,枚举,注释等将被放在一个无名的包(unnamed package)中。

    import语句

    在 Java 中,如果给出一个完整的限定名,包括包名、类名,那么 Java 编译器就可以很容易地定位到源代码或者类。import 语句就是用来提供一个合理的路径,使得编译器可以找到某个类。

    例如,下面的命令行将会命令编译器载入 java_installation/java/io路径下的所有类

    1. 如果在一个包中,一个类想要使用本包中的另一个类,那么该导包语句可以省略。
    2. 如果不在一个包中,一个类想要使用另外一个包中的一个类,那么要使用导包语句import 包名.*或者import 包名.类名 其,*符号标识导入该包下面所有的类(一般可以使用快捷键导入Alt+Enter)
    3. 类文件中可以包含任意数量的 import 声明。import 声明必须在包声明之后,类声明之前。

4、java的toString方法

现在只需要知道,当我们自定义一个类时,如果该类没有重写toString方法,那么,我们使用System.out.println(对象名)来输出对象只会在控制台得到该类的名称 + “@” + 该对象hashCode值的十六进制数字 类似于:Person@64c64813 当我们重写了toString方法,那么,我们就可以在这个方法里面自定义我们要输出的内容.

例子:

 public class Person {
    private int age;
    private String name;
    public Person() {
    }
    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person(age:" + age + ",name:" + name + ")";
    }
 
    public static void main(String[] args) {
        Person p = new Person(22, "Allen");
        Person p1 = new Person(18, "Peter");
        System.out.println(p);
        System.out.println(p1);
    }
}

输出结果: Person(age:22,name:Allen)

Person(age:18,name:Peter)

5、==和equal()方法区别

**==**符

用来专门用来比较值是否相等。分两种情况—基本数据类型的值 和 对象类型的地址(变量)

1)基本数据类型

int x = 1 ;
int y = 1 ;
System.out.println(x==y);

输出结果true

2)对象类型的地址(变量)

当变量指向的数据是对象类型,那么,这个时候数据是存放在两块内存中,例如如下代码

Student stu1  = new Student()
Student stu2  = new Student()
System.out.println(stu1 == stu2)

每当实例化一个类如Student stu1 = new Student()时候,此时变量名(stu1)存放在栈内存,而new Student()存放于堆内存中,

此时比较的是两个是否指向同一引用地址,此时返回flase,因为实例化了两个类,内存地址不一样。

equals()方法

equals()方法是用于比较两个对象的内容是否相等

Student stu1  = new Student()
Student stu2  = new Student()
System.out.println(stu1.equals(stu2))

stu1和stu2的内存地址虽然不一样的,但是两个对象的内容是一样的,所以返回结果是true

6、java中的基本数据类型

八大基本类型的封装类型(集合的时候会用到)

Java中每一种基本类型都会对应一个唯一的包装类,基本类型与其包装类都可以通过包装类中的静态或者成员方法进行转换。每种基本类型及其包装类的对应关系如下,值得注意的是,所有的包装类都是final修饰的,也就是它们都是无法被继承和重写的。

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

基本类型与包装类型的异同

1、在Java中,一切皆对象,但八大基本类型却不是对象。

2、声明方式的不同,基本类型无需通过new关键字来创建,而封装类型需new关键字,所有包装类型变量中存储的也是引用。

3、存储方式及位置的不同,基本类型是直接存储变量的值保存在堆栈中能高效的存取,封装类型需要通过引用指向实例,具体的实例保存在堆中。

4、初始值的不同,封装类型的初始值为null,基本类型的的初始值视具体的类型而定,比如int类型的初始值为0,boolean类型为false;

有的包装类都是final修饰的,也就是它们都是无法被继承和重写的。

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

基本类型与包装类型的异同

1、在Java中,一切皆对象,但八大基本类型却不是对象。

2、声明方式的不同,基本类型无需通过new关键字来创建,而封装类型需new关键字,所有包装类型变量中存储的也是引用。

3、存储方式及位置的不同,基本类型是直接存储变量的值保存在堆栈中能高效的存取,封装类型需要通过引用指向实例,具体的实例保存在堆中。

4、初始值的不同,封装类型的初始值为null,基本类型的的初始值视具体的类型而定,比如int类型的初始值为0,boolean类型为false;

5、使用方式的不同,比如与集合类合作使用时只能使用包装类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值