Java基础知识(2)- Java 类和对象、基本数据类型和变量类型
1. Java 类和对象
Java 作为一种面向对象语言,在面向对象中,类和对象是最基本、最重要的组成单元。
类是表示一个客观世界某类群体的一些基本特征抽象。对象就是表示一个个具体的东西。类是对象的抽象,对象是类的具体(或实体)。
类是描述了一组有相同特性(属性)和相同行为(方法)的一组对象的集合。 对象(或实体)所拥有的特征在类中表示时称为类的属性,对象执行的操作称为类的方法。
类是构造面向对象程序的基本单位,是抽取了同类对象的共同属性和方法所形成的对象(或实体)的 “模板”。对象是现实世界中实体的描述,对象要创建才存在,有了对象才能对对象进行操作。
类是对象的模板,对象是类的实例。
1)Java类
通过下面 Person 类来理解 Java 中类的定义:
1 class Person { 2 3 String name; // 成员变量, default 访问权限,同一包中的类可以访问; 具有默认值, 无需初始化 4 static int age = 20; // 类变量(静态变量) 5 6 // 构造方法 7 public Person() { 8 } 9 10 // 重载(Overload)带参数构造方法 11 public Person(String name) { 12 this.name = name; 13 } 14 15 // 成员方法,该方法内可以访问本类的静态和非静态成员 16 public String getName(){ 17 return name; 18 } 19 20 // 静态方法,该方法内不能访问本类的非静态成员 21 public static int getAge() { 22 int a = 1; // 局部变量,需要初始化 23 return age + a - 1; 24 } 25 26 }
(1) 类中的方法:
成员方法(或实例方法):一个方法如果不加static关键字,那么这个方法是实例方法。意思是他属于类的某个实例,通过这个实例调用它,对类的其他实例不产生影响。
类方法(静态方法):在方法前加 static 关键字,就代表这个方法属于这个类本身,不属于他的任何实例,所有的实例都共享这一个方法,对方法的调用各个实例相互可见。
构造方法(或构造函数、构造器):构造方法是类的一种特殊方法,用来初始化类的一个新的对象,在创建对象(new 运算符)之后自动调用。
(2) 类中的变量:
局部变量:在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。
成员变量(或实例变量):成员变量是定义在类中,方法之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。
类变量(或静态变量):类变量也声明在类中,方法之外,但必须声明为 static 类型。
(3) 构造方法(或称构造函数、构造器)
每个类都有构造函数。如果没有显式地为类定义构造函数,Java编译器将会为该类提供一个默认构造函数。
在创建一个对象的时候,至少要调用一个构造函数。构造函数的名称必须与类同名,一个类可以有多个构造函数。
子类是不继承父类的构造方法,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。
如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。
Java 构造方法有以下特点:
(1) 方法名必须与类名相同
(2) 可以有0个、1 个或多个参数
(3) 没有任何返回值,包括 void
(4) 默认返回类型就是对象类型本身
(5) 只能与 new 运算符结合使用
值得注意的是,如果为构造方法定义了返回值类型或使用 void 声明构造方法没有返回值,编译时不会出错,但 Java 会把这个所谓的构造方法当成普通方法来处理。
2)Java创建对象
(1) 使用 new 关键字创建对象
语法格式:
类名 对象名 = new 类名();
(2) 调用 java.lang.Class 或者 java.lang.reflect.Constuctor 类的 newlnstance() 实例方法
语法格式:
java.lang.Class 对象名1 = java.lang.Class.forName(类名);
类名 对象名2 = (类名) 对象名1.newInstance();
调用 forName() 方法时,类名需要类的全称(比如 com.xxx.xxx);
(3) 调用对象的 clone() 方法
该方法不常用,使用该方法创建对象时,要实例化的类必须继承 java.lang.Cloneable 接口。
语法格式:
类名对象名 = (类名) 已创建好的类对象名.clone();
(4) 调用 java.io.ObjectlnputStream 对象的 readObject() 方法
从一个对象的class文件,可以进行反序列化操作,调用 ObjectInputStream 的 readObject() 方法。
(5) 隐含创建对象
除了显式创建对象以外,在 Java 程序中还可以隐含地创建对象,例如下面几种情况。
a) String str = "test","test"就是一个 String 对象,由 Java 虚拟机隐含地创建;
b) 字符串的 “+” 运算符运算的结果为一个新的 String 对象;
C) 当 Java 虚拟机加载一个类时,会隐含地创建描述这个类的 Class 实例;
提示:类的加载是指把类的 .class 文件中的二进制数据读入内存中,把它存放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class 对象,用来封装类在方法区内的数据结构。
3) Java包(Package)
为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。
包的作用:
(1) 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用;
(2) 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突;
(3) 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类;
语法格式:
package pkg1[.pkg2[.pkg3…]];
4) Import语句
在 Java 中,如果给出一个完整的限定名,包括包名、类名,那么 Java 编译器就可以很容易地定位到源代码或者类。Import 语句就是用来提供一个合理的路径,使得编译器可以找到某个类。
例如,下面的命令行将会命令编译器载入 java_installation/java/io 路径下的所有类
import java.io.*;
5) 源文件声明规则
当在一个源文件中定义多个类,并且还有import语句和package 语句时,要特别注意这些规则。
(1) 一个源文件中只能有一个 public 类;
(2) 一个源文件可以有多个非 public 类;
(3) 源文件的名称应该和 public 类的类名保持一致。例如:源文件中public类的类名是 Person,那么源文件应该命名为 Person.java;
(4) 如果一个类定义在某个包中,那么package语句应该在源文件的首行。
(5) 如果源文件包含 import 语句,那么应该放在 package 语句和类定义之间。如果没有 package 语句,那么 import 语句应该在源文件中最前面。
(6) import 语句和 package 语句对源文件中定义的所有类都有效。在同一源文件中,不能给不同的类不同的包声明。
类有若干种访问级别,并且类也分不同的类型:抽象类和final类等。Java 还有一些特殊的类,如:内部类、匿名类。
2. Java 基本数据类型
变量就是申请内存来存储值。也就是说,当创建变量的时候,需要在内存中申请空间。
内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类型数据。
因此,通过定义不同类型的变量,可以在内存中储存整数、小数或者字符。
Java的两大数据类型:内置数据类型,引用数据类型
1)内置数据类型
Java语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。
(1) byte型:
byte数据类型是8位、有符号的,以二进制补码表示的整数;
最小值是-128(-2^7);
最大值是127(2^7-1);
默认值是0;
byte类型用在大型数组中节约空间,主要代替整数,因为byte变量占用的空间只有int类型的四分之一;
例子:byte a = 100,byte b = -50。
(2) short型(短整型):
short数据类型是16位、有符号的以二进制补码表示的整数
最小值是-32768(-2^15);
最大值是32767(2^15 - 1);
Short数据类型也可以像byte那样节省空间,一个short变量是int型变量所占空间的二分之一;
默认值是0;
例子:short s = 1000,short r = -20000。
(3) int型(整型):
int数据类型是32位、有符号的以二进制补码表示的整数;
最小值是-2,147,483,648(-2^31);
最大值是2,147,483,647(2^31 - 1);
一般地整型变量默认为int类型;
默认值是0;
例子:int a = 100000, int b = -200000。
(4) long(长整型):
long数据类型是64位、有符号的以二进制补码表示的整数;
最小值是-9,223,372,036,854,775,808(-2^63);
最大值是9,223,372,036,854,775,807(2^63 -1);
这种类型主要使用在需要比较大整数的系统上;
默认值是0L;
例子: long a = 100000L,long b = -200000L。
(5) float(单精度浮点型):
float数据类型是单精度、32位、符合IEEE 754标准的浮点数;
float在储存大型浮点数组的时候可节省内存空间;
默认值是0.0f;
浮点数不能用来表示精确的值,如货币;
例子:float f1 = 234.5f。
(6) double(双精度浮点型):
double数据类型是双精度、64位、符合IEEE 754标准的浮点数;
浮点数的默认类型为double类型;
double类型同样不能表示精确的值,如货币;
默认值是0.0d;
例子:double d1 = 123.4。
(7) boolean(布尔型):
boolean数据类型表示一位的信息;
只有两个取值:true和false;
这种类型只作为一种标志来记录true/false情况;
默认值是false;
例子:boolean one = true。
(8) char(字符型):
char类型是一个单一的16位Unicode字符;
最小值是’\u0000’(即为0);
最大值是’\uffff’(即为65,535);
char数据类型可以储存任何字符;
例子:char letter = ‘A’。
Float和Double的最小值和最大值都是以科学记数法的形式输出的,结尾的"E+数字"表示E之前的数字要乘以10的“数字”次幂。比如3.14E3就是3.14×1000=3140,3.14E-3就是3.14/1000=0.00314。
实际上,JAVA中还存在另外一种基本类型void,它也有对应的包装类 java.lang.Void,不过我们无法直接对它们进行操作。
2)引用数据类型
引用类型变量由类的构造方法(或构造函数)创建,可以使用它们访问所引用的对象。这些变量在声明时被指定为一个特定的类型,比如 Person 等。变量一旦声明后,类型就不能被改变了。
对象、数组都是引用数据类型。
所有引用类型的默认值都是null。
一个引用变量可以用来引用与任何与之兼容的类型。
3)Java常量
常量指不能改变的量。常量有三种类型:静态常量、成员常量和局部常量。
Java 语言使用 final 关键字来定义一个常量,其语法如下所示:
final dataType variableName = value
其中,final 是定义常量的关键字,dataType 指明常量的数据类型,variableName 是变量的名称,value 是初始值。
public class App {
// 静态常量, public static 修饰的常量作用域是全局的,不需要创建对象就可以访问它
public static final double PI = 3.14;
// 声明成员常量, 作用域类似于成员变量
final int y = 10;
public static void main(String[] args) {
// 声明局部常量, 作用域类似于局部变量
final double x = 3.3;
}
}
在定义常量时,需要注意如下内容:
(1) 在定义常量时就需要对该常量进行初始化。
(2) final 关键字不仅可以用来修饰基本数据类型的常量,还可以用来修饰对象的引用或者方法。
(3) 为了与变量区别,常量取名一般都用大写字符。
3. Java 变量类型
Java 语言支持的变量类型有:
局部变量:类的方法中的变量。
实例变量:独立于方法之外的变量,没有 static 修饰。
类变量:独立于方法之外的变量,用 static 修饰。
声明变量的基本格式如下:
type identifier [ = value][, identifier [= value] ...] ;
type 为 Java 数据类型。identifier 是变量名。可以使用逗号隔开来声明多个同类型变量。
int a, b, c; // 声明三个int型整数:a、b、c。
int d = 3, e, f = 5; // 声明三个整数并赋予初值。
byte z = 22; // 声明并初始化z。
double pi = 3.14159; // 声明了pi。
char x = 'x'; // 变量x的值是字符'x'。
1) 局部变量
(1) 局部变量声明在方法、构造方法或者语句块中;
(2) 局部变量在方法、构造方法、或者语句块被执行的时候创建,当它们执行完成后,变量将会被销毁;
(3) 访问修饰符不能用于局部变量;
(4) 局部变量只在声明它的方法、构造方法或者语句块中可见;
(5) 局部变量是在栈上分配的。
(6) 局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。
2) 成员变量(或称实例变量)
(1) 成员变量声明在一个类中,但在方法、构造方法和语句块之外;
(2) 当一个对象被实例化之后,每个成员变量的值就跟着确定;
(3) 成员变量在对象创建的时候创建,在对象被销毁的时候销毁;
(4) 成员变量的值应该至少被一个方法、构造方法或者语句块引用,使得外部能够通过这些方式获取成员变量信息;
(5) 成员变量可以声明在使用前或者使用后;
(6) 访问修饰符可以修饰成员变量;
(7) 成员变量对于类中的方法、构造方法或者语句块是可见的。一般情况下应该把成员变量设为私有。通过使用访问修饰符可以使成员变量对子类可见;
(8) 成员变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是 false,引用类型变量的默认值是 null。变量的值可以在声明时指定,也可以在构造方法中指定;
(9) 成员变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:ObejectReference.VariableName。
3) 类变量(静态变量)
(1) 类变量也称为静态变量,在类中以 static 关键字声明,但必须在方法、构造方法和语句块之外。
(2) 无论一个类创建了多少个对象,类只拥有类变量的一份拷贝。
(3) 静态变量除了被声明为常量外很少使用。常量是指声明为 public/private,final 和 static 类型的变量。常量初始化后不可改变。
(4) 静态变量储存在静态存储区。经常被声明为常量,很少单独使用 static 声明变量。
(5) 静态变量在程序开始时创建,在程序结束时销毁。
(6) 与成员变量具有相似的可见性。但为了对类的使用者可见,大多数静态变量声明为 public 类型。
(7) 默认值和实例变量相似。数值型变量默认值是0,布尔型默认值是 false,引用类型默认值是 null。变量的值可以在声明的时候指定,也可以在构造方法中指定。此外,静态变量还可以在静态语句块中初始化。
(8) 静态变量可以通过:ClassName.VariableName 的方式访问。
(9) 类变量被声明为 public static final 类型时,类变量名称必须使用大写字母。如果静态变量不是 public 和 final 类型,其命名方式与成员变量以及局部变量的命名方式一致。
实例:
1 package com.example; // 包名 2 3 class Person { 4 String name; // 成员变量, default 访问权限,同一包中的类可以访问; 具有默认值, 无需初始化 5 static int age = 20; // 类变量(静态变量) 6 7 // 构造方法 8 public Person() { 9 System.out.println("Person() 构造方法"); 10 } 11 12 // 重载(Overload)带参数构造方法 13 public Person(String name) { 14 this.name = name; 15 System.out.println("Person(" + name + ") 构造方法"); 16 } 17 18 // 成员方法,该方法内可以访问本类的静态和非静态成员 19 public String getName(){ 20 return name + " (" + age + ")"; 21 } 22 23 // 静态方法,该方法内不能访问本类的非静态成员 24 public static int getAge() { 25 int a = 1; // 局部变量,需要初始化 26 return age + a - 1; 27 } 28 29 } 30 31 public class App { 32 33 // 静态常量, public static 修饰的常量作用域是全局的,不需要创建对象就可以访问它 34 public static final double PI = 3.14; 35 // 声明成员常量, 作用域类似于成员变量 36 final int y = 10; 37 38 public static void main( String[] args ) { 39 40 // 声明局部常量, 作用域类似于局部变量 41 final double x = 3.3; 42 43 // 44 Person person1 = new Person(); 45 System.out.println("person1.getName(): " + person1.getName()); 46 47 Person person2 = new Person("Tester"); 48 System.out.println("person2.getName(): " + person2.getName()); 49 System.out.println("person2.getAge(): " + person2.getAge()); 50 51 System.out.println("Person.getAge(): " + Person.getAge()); 52 System.out.println("Person.age: " + Person.age); 53 54 System.out.println("--------------------------------------------------------------"); 55 System.out.println("typeTest"); 56 System.out.println(""); 57 58 System.out.println("PI: " + PI); 59 System.out.println("y: " + new App().y); 60 System.out.println("x: " + x); 61 System.out.println(""); 62 63 // 调用本类的静态方法 64 typeTest(); 65 66 } 67 68 // 静态方法 69 public static void typeTest(){ 70 71 // byte 72 System.out.println("基本类型:byte 二进制位数:" + Byte.SIZE); 73 System.out.println("包装类:java.lang.Byte"); 74 System.out.println("最小值:Byte.MIN_VALUE=" + Byte.MIN_VALUE); 75 System.out.println("最大值:Byte.MAX_VALUE=" + Byte.MAX_VALUE); 76 System.out.println(); 77 78 // short 79 System.out.println("基本类型:short 二进制位数:" + Short.SIZE); 80 System.out.println("包装类:java.lang.Short"); 81 System.out.println("最小值:Short.MIN_VALUE=" + Short.MIN_VALUE); 82 System.out.println("最大值:Short.MAX_VALUE=" + Short.MAX_VALUE); 83 System.out.println(); 84 85 // int 86 System.out.println("基本类型:int 二进制位数:" + Integer.SIZE); 87 System.out.println("包装类:java.lang.Integer"); 88 System.out.println("最小值:Integer.MIN_VALUE=" + Integer.MIN_VALUE); 89 System.out.println("最大值:Integer.MAX_VALUE=" + Integer.MAX_VALUE); 90 System.out.println(); 91 92 // long 93 System.out.println("基本类型:long 二进制位数:" + Long.SIZE); 94 System.out.println("包装类:java.lang.Long"); 95 System.out.println("最小值:Long.MIN_VALUE=" + Long.MIN_VALUE); 96 System.out.println("最大值:Long.MAX_VALUE=" + Long.MAX_VALUE); 97 System.out.println(); 98 99 // float 100 System.out.println("基本类型:float 二进制位数:" + Float.SIZE); 101 System.out.println("包装类:java.lang.Float"); 102 System.out.println("最小值:Float.MIN_VALUE=" + Float.MIN_VALUE); 103 System.out.println("最大值:Float.MAX_VALUE=" + Float.MAX_VALUE); 104 System.out.println(); 105 106 // double 107 System.out.println("基本类型:double 二进制位数:" + Double.SIZE); 108 System.out.println("包装类:java.lang.Double"); 109 System.out.println("最小值:Double.MIN_VALUE=" + Double.MIN_VALUE); 110 System.out.println("最大值:Double.MAX_VALUE=" + Double.MAX_VALUE); 111 System.out.println(); 112 113 // char 114 System.out.println("基本类型:char 二进制位数:" + Character.SIZE); 115 System.out.println("包装类:java.lang.Character"); 116 // 以数值形式而不是字符形式将Character.MIN_VALUE输出到控制台 117 System.out.println("最小值:Character.MIN_VALUE=" + (int) Character.MIN_VALUE); 118 // 以数值形式而不是字符形式将Character.MAX_VALUE输出到控制台 119 System.out.println("最大值:Character.MAX_VALUE=" + (int) Character.MAX_VALUE); 120 } 121 }
输出:
Person() 构造方法
person1.getName(): null (20)
Person(Tester) 构造方法
person2.getName(): Tester (20)
person2.getAge(): 20
Person.getAge(): 20
Person.age: 20
--------------------------------------------------------------
typeTest
PI: 3.14
y: 10
x: 3.3
基本类型:byte 二进制位数:8
包装类:java.lang.Byte
最小值:Byte.MIN_VALUE=-128
最大值:Byte.MAX_VALUE=127
基本类型:short 二进制位数:16
包装类:java.lang.Short
最小值:Short.MIN_VALUE=-32768
最大值:Short.MAX_VALUE=32767
基本类型:int 二进制位数:32
包装类:java.lang.Integer
最小值:Integer.MIN_VALUE=-2147483648
最大值:Integer.MAX_VALUE=2147483647
基本类型:long 二进制位数:64
包装类:java.lang.Long
最小值:Long.MIN_VALUE=-9223372036854775808
最大值:Long.MAX_VALUE=9223372036854775807
基本类型:float 二进制位数:32
包装类:java.lang.Float
最小值:Float.MIN_VALUE=1.4E-45
最大值:Float.MAX_VALUE=3.4028235E38
基本类型:double 二进制位数:64
包装类:java.lang.Double
最小值:Double.MIN_VALUE=4.9E-324
最大值:Double.MAX_VALUE=1.7976931348623157E308
基本类型:char 二进制位数:16
包装类:java.lang.Character
最小值:Character.MIN_VALUE=0
最大值:Character.MAX_VALUE=65535
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)