Java类成员、面向对象的基本特征
- 1、类的成员一:属性
- 2、类的成员二:方法
- 3、类的成员三:构造器
- 4、类的第四个成员:代码块
- 5、类的第五个成员:内部类
类的5个成员:属性、方法、构造器、代码块、内部类
Java的3大基本特性:封装、继承、多态
----封装:安全、简单方便、对使用者隐藏实现细节
----继承:代码复用、扩展,表示is-a的关系
----多态:提高代码灵活性,增强代码功能
1、类的成员一:属性
属性:类的数据描述特征
1.1 属性的基本特性
1.1.1 声明的位置:
在类中方法外
1.1.2 声明的格式:
【修饰符】 数据类型 属性名;
1.1.3 属性的特点
(1)当创建对象后,没为属性赋值,那么
属性默认值和数组的元素的默认值是一样的
:
byte,short,int,long:0
float,double:0.0
char:\u0000或说是Unicode编码为0的字符
boolean:false
引用数据类型:null
(2)每一个对象的属性在堆中是互相独立
1.1.4 如何为对象的属性赋值
(1)显式初始化
class Circle{
//显式初始化
//每次创建圆的对象,半径的初始值都是1.0,而不是原来的0.0
double radius = 1.0;
}
(2)手动赋值(其他类中)
对象名.属性 = 值;
public static void main(String[] args){
Circle c1 = new Circle();
c1.radius = 2.0;//手动赋值
}
1.1.5 如何访问对象的属性值
(1)本类中
★直接属性名
class Circle{
double radius;
double getArea(){
return Math.PI * radius * radius;//直接访问
}
}
(2)其他类中
★对象名.属性名
public static void main(String[] args){
Circle c1 = new Circle();
c1.radius = 2.0;
System.out.println("圆的半径是:" + c1.radius);
}
1.2 成员变量与局部变量的区别
(1)
声明的位置不同
局部变量:(1)方法体{}(2)形参(3)代码块中
成员变量:声明的位置,类中方法外:(1)类变量:static修饰(2)实例变量:没static修改
(2)存储的位置不同
局部变量:栈
成员变量:堆
(3)初始值的获取方式不同
局部变量:必须手动初始化
成员变量:如果没初始化,它默认值,也可以手动初始化(方式很多种)
(4)生命周期
局部变量:短,从代码运行到声明它的语句开始,到它的作用域结束就结束,每一个线程,每一次调用执行都是全新的生命周期
实例变量:随着对象的创建而出生,随着对象的回收而消亡,和对象同生共死
类变量:最长?
(5)作用域
局部变量:从声明处开始,到它所属的}结束
成员变量(实例变量、类变量)不谈作用域,在本类中,直接访问,其他类中用"对象."访问
(6)修饰符
局部变量:要么没,要么只能一个final
成员变量:可以没,如果可以很多…
1.3 属性的私有化-权限修饰符
一个类的属性,对外界想要控制访问,那么可以给属性设置修饰符,例如:private
权限修饰符/访问控制修饰符:可见的范围从小到大
范围 | 本类 | 本包 | 其他包子类 | 其他包非子类 |
---|---|---|---|---|
private | 可以 | 不可以 | 不可以 | 不可以 |
缺省 | 可以 | 可以 | 不可以 | 不可以 |
protected | 可以 | 可以 | 可以 | 不可以 |
public | 可以 | 可以 | 可以 | 可以 |
权限修饰符可以修饰:属性、方法、构造器、内部类
其中的public和缺省,还可以修改类
回忆:
属性的声明: 【修饰符】 数据类型 属性名;类的声明: 【修饰符】 class 类名{ }
1.4 对象的内存分析
Java的内存分析图:
Java程序是运行在JVM中,JVM的功能之一:内存管理
(1)虚拟机栈,简称栈:存储局部变量
(2)堆:存储new出来的实例对象,包括数组
(3)方法区:用来存储不怎么变的东西,例如:加载的类的信息、静态的变量等
(4)本地方法栈:native等C语言实现的方法的变量等
(5)程序计数器:每一个线程当前运行到哪一个指令等信息
JVM高级时,还会再详细讲解,内存管理,以及垃圾回收的算法,内存优化
2、对象的内存结构图
对象的属性:存储在堆中
每一个对象的属性:每一个对象是独立的
1.5 对象数组
对象数组:它的元素数据类型是引用数据类型
例如:String[] ,Student[], Circle[]等
1.5.1 声明对象数组
元素的数据类型[] 数组名;
1.5.2 对象数组初始化
1、静态初始化
class TestObjectArray{
public static void main(String[] args){
//对象数组的静态初始化
/*
String[] array = {"hello","world","java"};
//foreach遍历
for(String str : array){
System.out.println(str);
}
*/
Circle[] array = {
new Circle(),new Circle(),new Circle()};//这个圆对象是匿名对象
//但是可以通过array[0],array[1],array[2]可以访问它,代表他,array[0],array[1],array[2]就好比是对象名
//foreach遍历
for(Circle c : array){
System.out.println(c.radius);
}
//Circle c = new Circle();//不仅创建了一个对象,并且取名为c,可以称c为对象名或对象的引用
}
}
class Circle{
double radius;
}
2、动态初始化
(1)先指定数组的长度
(2)为元素赋值为一个对象
class TestObjectArray2{
public static void main(String[] args){
//1、声明数组
Circle[] array;//元素的数据类型是Circle,说明该数组中只能存储圆对象,不能存别的
//2、动态初始化
//(1)指明数组的长度:要说明一共可以存几个元素,圆对象
array = new Circle[3];
//此时元素都是null
//(2)为元素赋值,此处是赋值为一个圆对象
array[0] = new Circle();
}
}
class Circle{
double radius;
}
1.5.3 对象数组的内存图
2、类的成员二:方法
2.1 方法的基本特性
2.1.1 方法的概念
方法(Method,又称为函数(Function,表示一个独立的功能。
在Java中作为类的成员。
2.1.2 使用的原则、特点
1、先声明后使用(和变量、类等一样)
2、不调用不执行,调用一次执行一次
3、一个方法最多只能返回一个结果,如果有多个数据,那么需要容器装进起来
2.1.3 声明和调用格式要求
1、声明的格式;
在类中方法外:
【修饰符】 返回值类型 方法名(【形参列表】【抛出的异常列表】{
方法体:功能的实现代码
【return 返回值;】
}
说明:
(1)方法名:第一个单词首字母小写,从第二个单词开始首字母大写;见名知意;
(2)返回值类型
A:如果方法的功能完成后不需要给调用者返回结果,那么声明方法时,返回值类型的位置用void表示。
B:如果方法的功能完成后需要给调用者返回结果,那么声明方法时,返回值类型的位置就不能用void,具体的类型由结果的类型决定。
返回值的类型可以是任意类型。
C:如果返回值类型的位置不是void,那么在方法体中必须保证一定有return 返回值;的语句。
而且不管当前方法从哪个分支结束,都需要有对应的return 返回值;语句。
D:一个方法只能有一个返回值。如果需要返回多个值,那么就要用数组或集合等装起来作为一个整体的结果返回。
(3)形参列表
A:如果当前方法的功能完成,需要调用者传递数据来辅助功能的完成,那么就通过形参体现出来,否则就不需要声明形参。
B:如果方法需要声明形参,那么格式是(数据类型 形参名,数据类型 形参名 。。。。),每一个形参用,分割,且都要有数据类型
C:形参就是一个方法的局部变量,而且声明时值是不确定的,是要在调用时有实参类决定
D:如果某个形参的值的个数不确定,可以声明为可变参数
2、调用格式
(1)本类中
直接使用:方法名(【实参列表】)
(2)其他类中
必须通过对象:对象.方法名(【实参列表】)
说明:
(1)如果被调用的方法的返回值类型位置是void
那么该调用语句就必须单独成一个语句。
(2)如果被调用的方法的返回值类型位置不是void
那么如果调用者需要这个返回值,那么就用变量接收 或者 直接打印 或者 用这个返回值再参与其他计算。
(3)如果被调用的方法的形参列表是空的()
那么调用时不需要传实参
(4)如果被调用的方法的形参列表不是空的(形参列表)
那么调用时,一定要传实参的,而且实参的类型(一致或兼容)、个数、顺序与形参列表要一一对应。
2.1.4 总结
(1)本类中直接用,其他类用对象.
(2)返回值就接收,无返回值就别接收
(3)形参就传实参,没形参就不传实参,实参的作用就是给形参传值
(4)返回值类型:如果是void,说明没有返回值
如果是其他的,说明有返回值
方法形式有四种:
1、无参无返回值
2、有参无返回值
3、无参有返回值
4、有参有返回值
2.2 方法的参数传递机制
方法的参数的传递:实参-->形参(值传递)
形参:声明/定义方法()中的参数,被调用方法的()中的参数
实参:调用方法()中的参数
2.2.1 基本数据类型:8种
`实参给形参传 数据值`
`形参对值的修改 不会 影响实参的值`
2.2.2 引用数据类型:类、接口、数组等
`实参给形参传 地址值`
`形参对象对属性的修改 会 影响实参对象的属性`(本质上它俩就是同一个对象)
(陷阱)当形参重新new对象了,那么和实参就没有关系了,形参在修改属性,和实参就没关系了
(特殊)String类型比较特殊,它的对象有不可变性,所有的改变都会产生新的String对象,类似这样的对象,还有包装类对象等
2.3 方法重载
2.3.1 概念:方法的重载(Overload):(个人理解实质上就是形参列表不一样)
在同一个类中,出现了方法名称相同,但是形参列表不同的两个或多个方法,称为方法的重载。
和返回值类型无关。
2.3.2 例如:
public int max(int a, int b){
System.out.println("2个整数的最大值");
return a > b ? a : b;
}
public int max(int a, int b, int c){
System.out.println("三个整数的最大值");
int max = a>b ? a : b;
max = max > c ? max : c;
return max;
}
public double max(double a, double b){
System.out.println("两个小数的最大值");
return a > b ? a : b;
}
2.4 命令行参数
2.4.1 定义
给main()传递的实参,叫做命令行参数。
2.4.2 格式
1、命令行执行程序时中输入:java 主方法所在的类名 实参值1 实参值2 实参值3。。。。无穷无尽个
注:通过命令行编译正常进行,运行时候在正常的“java 主方法所在的类名”后边加上+空格+实参值1+空格+实参值2+...可以无穷多个
2、编译的是main(String[] args)引用类型数组
class TestCommandParamExer{
public static void main(String[] args){
System.out.println("长度:" + args.length);
for(int i=0; i<args.length; i++){
System.out.println(args[i]);
}
//-------------求和-----------
int sum = 0;
for(int i=0; i<args.length; i++){
//sum += args[i];//不兼容的类型: String无法转换为int
sum += Integer.parseInt(args[i]);//Integer.parseInt(字符串)把字符串转成整数int
}
System.out.println("和:" + sum);
}
}
2.5 可变参数
2.5.1 可变参数:某个方法调用时,实参的个数是可变的。
格式:(数据类型... 可变参数名)
2.5.2 要求
(1)一个方法只能有一个可变参数
(2)可变参数必须在形参列表的最后
3、如何使用可变参数
(1)在声明它的方法中:当做数组使用
(2)可变参数对应的实参,个数可以是0-n个,但是类型必须对应
(3)特殊的情况:可变参数对应的实参,可以是一个对应类型的数组
例:
public static int sum_num(int... num) {
int su = 0;
for (int i = 0; i < num.length; i++) {
su += num[i];
}
return su;
}
2.6 Java基本特征之一:封装
2.6.1 封装的目的:隐藏实现细节,为了安全,也为了使用者方便
2.6.2 封装
(1)属性的封装
:
一般情况下:
权限修饰符:private私有化
提供标准的get/set方法
(2)方法的封装
:封装的是一个独立的功能,一段代码
(3)类的封装
(4)组件的封装
:例如使用第三方的组件,支付宝,网银支付,对方给你开放了接口,你按照它规定的格式,把数据传给它,它计算完,把结果返回。
(5)系统的封装
:对于使用者来说,不知道实现细节,但是知道怎么用。
2.6.3 标准的JavaBean格式get/set的格式
(1)get方法:
【修饰符】 属性的类型 get属性名首字母大写(){
return 属性;
}
(2)set方法:
【修饰符】void set属性名首字母大写(属性的类型 形参名){
....
this.属性 = 形参名;
}
(3)特别的是Boolean类型的属性,is属性名(属性的类型 形参名)
(4)最好保留无参构造
3、类的成员三:构造器
3.1 构造器的作用:
(1)和new一起使用时,用来创建对象:
new新对象时意思就是在运行这个构造器
new 构造器名(参数列表)
(2)构造器可以为属性赋初始值
3.2 构造器的声明和调用
1、构造器的声明:位置:类中,方法外
语法格式:
//无参构造
【修饰符】 构造器名(){
}
//有参构造
【修饰符】 构造器名(形参列表){
}
说明:构造器没有返回值类型,也不写void
2、如何调用构造器:
(1)在非本类构造器中
调用无参构造:
new 构造器名()
调用有参构造:
new 构造器名(实参列表)
(2)在本类的构造器中?(留着)
(3)在子类的构造器中?(留着)
3、所以,创建对象的格式:
之前:
类名 对象名 = new 类名();
现在:
类名 对象名 = new 构造器名();//无参构造
类名 对象名 = new 构造器名(实参列表);//有参构造
3.3 特点
(1)构造器的名称必须与所在的类名完全相同
(2)所有的类都有构造器,如果一个类没有显式声明构造器,
那么这个类在编译时,将自动生成一个无参的构造器。
如果显式声明了构造器,那么编译器将不再添加默认的无参构造。
(3)构造器可以重载
(4)构造器没返回值类型
(5)构造函数的修饰符只能是权限修饰符(public、缺省、protect、private)
其他的(static、final、abstract)都不行
3.4 this关键字
this的意思:当前对象,本类的调用
(1)构造器中
this当前对象表示的是正在new(创建)的那个对象
(2)成员方法中(非静态方法中)
this当前对象表示的是调用该方法的对象
(3)静态方法中不能用this关键字
用法:
(1)
this.属性 或 this.成员变量
当在某个方法中(构造器、成员方法),如果出现了局部变量(例如:形参和成员变量)属性重名了,
那么用“this.属性”进行区分。
如果该方法中不涉及到局部变量与属性重名问题,在属性的前面加不加this.都可以。
(2)this.方法
用this.方法表示访问当前对象的方法,完全可以省略this.
(3)this()
或this(实参列表)
用于调用本类的其他构造器,必须在构造器的首行。第一句。要避免递归调用。
this()用于表示调用本类的无参构造
this(实参列表)用于表示调用本类的有参构造
3.5 包
3.5.1 包的作用:
(1)避免类的重名
有了包之后,类的全名称就变成了:包.类名
(2)管理类等资源文件
(3)顺便,控制某些类、成员的访问权限
3.5.2 如何声明包:表示当前源文件中的所有类都是该包下的。
格式:package 包名;
位置:必须在源文件的首行
包名,全部单词都小写,单词之间使用.分割,一般使用域名倒置 + 模块名
3.5.3 包名的规范:
(1)全部都小写,每一个单词之间使用.
(2)见名知意
(3)包名习惯上,用公司的域名倒置 + 模块名;
(4)包的修饰符注:
公司的域名:www.meituan.com
常见项目中的包:
com.meituan.bean;
com.meituan.util;
com.meituan.dao;
com.meituan.service;
…
常见的一级二级域名:
c