java-day10

1. 面向对象

1.1 传值和传引用
基本数据类型保存值的大小,而数据类型保存内存地址
传值是基本数据类型 传引用是引用类型
局部变量 属于栈帧私有化,栈帧独享

package com.demos;

public class Test02 {

	public static void main(String[] args) {
		int i = 10;
		//m1---->11
		//10
		//首先执行m1方法 此时输出11,由于是基本数据类型,m1方法执行后i的值不会改变,main输出的i还是为10
		m1(i);
		System.out.println("main--->"+i);
		
		Animal a = new Animal(18);
		System.out.println(a);//com.demos.Animal@15db9742
		m2(a);//a a1 地址都相同
		System.out.println("main--->"+a.age);//由于 a 是引用类型,因数据改变而改变,a 只是一个地址,指向堆内存,如果堆内存该地址的数据改变,那么指向它地址数据也会改变,而不是改变之前的数据
		
		
	}
	public static void m1(int i) {
		i++;
		System.out.println("m1---->"+i);
	}
	public static void m2(Animal a1) {
		System.out.println(a1);//com.demos.Animal@15db9742
		a1.age++;
		System.out.println("m2--->"+a1.age);
	}

}
class Animal{
	int age;
//	Animal(int _age){
//		age = _age;
//	}
	Animal(int age){
		//加上this默认使用该参数的值,因此可以不同过变量名解决
		//不加上this,始终使用成员变量 age。
		//结果为19 19
		this.age = age;
		
		//这个结果为1 1
//		age = age;
	}
}

1.2 区分成员和构造
构造方法 :
[权限修饰符] 类名(参数) {方法体}

作用 : 创建对象,初始化成员属性

方法声明 : [修饰符列表] 返回值类型 方法名(参数) {方法体}

方法名符合命名规则即可 : 字母,下划线,美元符号,数字,不能数字开头,不能使用关键字和保留字,建议望文知义, 驼峰命名法

方法目的 : 代码重用性,提高代码效率
问题:
1 成员方法的方法名可以和类名相同吗?(成员方法可以和构造方法同名吗?)
可以和类名相同
2 如何区分同名的成员方法和构造方法?
看返回值,构造方法木有返回值,成员方法必须有返回值类型,如果没有用void表示.

package com.demos;

public class Test03 {

	public static void main(String[] args) {
		Test03 a = new Test03();
		a.Test03();
		

	}
	//构造方法没有放回值类型,连void 都没有
	public Test03() {
		System.out.println("构造方法");
	}
	//成员方法有返回值,void也算
	public void Test03() {
		System.out.println("成员方法");
	}
}

1.3 this
1.3.1 是什么?

this是每个对象中,保存自身内存地址的一个引用类型的成员变量
所以说,this就表示对象自己,相当于我们说 “我” 一样
1.3.2 能干什么?
1 在成员/构造方法中,能够区分同名的局部变量和成员变量
2 在构造方法中,也可以用于重载调用当前类中其他的构造方法(必须在第一行)
3 return this 返回当前对象内存地址,可以做到链式调用

1.3.3 怎么用
1.3.3.1 区分局部变量和成员变量

package com.demos01;

public class _01_This {
	int i = 1;
	public static void main(String[] args) {
		_01_This s1 = new _01_This();
		s1.i = 19;//对_01_This 成员变量赋值为19
		s1.m1();
		
	}
	// 1 区分同名的局部变量和成员变量
	public void m1() {
		// 成员方法中可以直接访问成员变量,因为俩在一起
		System.out.println(i);//19
		int i = 2;
		// 由于和成员变量同名,局部变量优先级高,所以直接访问i是局部变量
		System.out.println(i);//2
		
		// 通过对象区分 1 新建对象,访问的i是新建对象的i 并不是当前对象的i  
		 _01_This s = new _01_This();//s 与 s1 的地址不一样
		 System.out.println(s.i);//s地址指向堆中i的初始值为 1
		 
		 // 使用当前对象调用,因为s1是main方法中的局部变量,不能访问
		// System.out.println(s1.i);
		 
		 // 使用this调用,因为this就表当前对象(谁调用的这个成员方法,this就是谁)
		System.out.println(this.i);//this指向的地址为s1的地址,因为s1,调用了成员方法m1
	}
}
class User{
	//私有属性 age,只能User 该类访问
	private int age;
	
	public void setAge(int age) {
		this.age = age;
	}
	public int getAge() {
		return age;
	}
	//构造方法中 区分
	public User(int age) {
		this.age = age;//age是User有参方法的不是私有的成员变量的age
	}
}

1.3.3.2 重载调用构造方法
this重载调用当前类的其他构造方法
必须出现在构造方法第一行

语法 :
this(参数);

package com.demos01;

public class _02_This {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 创建时间对象1
		MyDate date1 = new MyDate();
		date1.setYear(2021);
		date1.setMonth(1);
		date1.setDay(13);
		// 2021 年 1 月 13 日 
		date1.println();
		
		// 创建时间对象2
		MyDate date2 = new MyDate();
		// 0 年 0 月 0 日 
		date2.println();
		
		// 需求 : 创建时间的时候 必须有日期(需要提供一个有参构造,在创建对象的时候,对三个变量赋值)
		MyDate date3 = new MyDate(2021,1,13);
		date3.println();
		
		// 需求 : 如果不传入时间,默认时间为 1970年1月1日(创建无参构造,在无参构造中对变量赋值)
		MyDate date4 = new MyDate();
		// 1970 年 1 月 1 日 
		date4.println();
	}

}
//创建时间类
class MyDate{
	private int year;
	private int month;
	private int day;
	
//	创建,获取成员变量
	public int getYear() {
		return year;
	}
	public void setYear(int year) {
		this.year = year;
	}
	public int getMonth() {
		return month;
	}
	public void setMonth(int month) {
		this.month = month;
	}
	public int getDay() {
		return day;
	}
	public void setDay(int day) {
		this.day = day;
	}
	// 全参构造
	public MyDate(int year, int month, int day) {
		this.year = year;
		this.month = month;
		this.day = day;
	}
	// 无参构造
	public MyDate() {
		// this.year = 1970;
		// this.month = 1;
		// this.day = 1;
		// 上面代码,和有参构代码重复,如果是有100行代码呢?就需要再写100行代码

		// 重载调用有参构造,必须在有效代码的第一行
		this(1970, 1, 1);//里面参数为三个所以地址为三个参数的构造函数地址
	}
	// 打印
	public void println() {
		System.out.println(this.year + " 年 " + month + " 月 " + day + " 日 ");
	}

}

1.3.3.3 链式调用
链式调用 : xxx.方法().方法().方法()…

核心点 : 前者方法返回值一定是可以调用后者方法的 引用

package com.demos01;

public class _03_This {

	public static void main(String[] args) {
		_03_This t = new _03_This();
		// 成员方法调用应该用对象调用
		// 方法在哪个类中,就用哪个类的对象调用
		// 所以 t 是_03_This类型 
		t.m1();
		t.m2();
		
		// 链式调用
		t.m1().m2();//t调用了m1,则返回的地址为t的地址相当于t.m2()等价
	}

	public _03_This m1() {
		System.out.println("m1执行了");
		// 谁调用的这个方法,this就是谁,这里把这个对象地址返回
		return this;
	}

	public void m2() {
		System.out.println("m2执行了");
	}



}

1.3.4 注意
this 不能出现在静态上下文中
在这里插入图片描述

1.4 static
1.4.1 是什么?
static是一个修饰符关键字,用来区别静态和动态属性
1.4.2 能干什么?
static修饰符
1 static修饰的类体中的变量是静态变量
2 static修饰的方法是静态方法
3 static修饰的语句块是静态语句块
1.4.3 怎么用
static修饰符
1、 static修饰的类体中的变量是静态变量
2 、static修饰的方法是静态方法
3 、static修饰的语句块是静态语句块

语法 : static { java代码; }

静态语句块是在类加载阶段执行,并且只执行一次,并且是从上往下执行

静态变量也是在类加载阶段初始化,并且和静态语句块没有优先级之分,从上向下执行初/初始化,所以 不能再静态语句块中 提前使用静态变量,而在方法中是可以的

什么情况下 类加载 : 访问某个类的静态属性的时候,类加载

package com.demos02;

public class _01_Static {
	/**
	 * 打印结果
	 * 	静态语句块1
		1
		静态语句块2
		main------------>
			
		static 是属于类级别的,程序运行时会进行类加载,这个加载比main方法要早,加载到静态区
		所以先执行静态语句块 执行一次就结束!。
	 * */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("main------------>");
	}
	static {
		// 报错,说明 静态语句块和静态变量都是在类加载阶段初始化的,初始化优先级一致
		// 从上往下初始化,所以 执行该代码段的时候,变量i还没有被初始化,所以报错
		//Cannot reference a field before it is defined
//		 System.out.println(i);
		System.out.println("静态语句块1");
	}
	public static void m2() {
		// 因为方法不调用不执行
		// 而调用执行只能在执行阶段才可以,而静态变量是在加载阶段
		// 所以 能够保证 在执行m2方法的时候,变量i一定是存在的,所以 可以再变量声明之前使用
		System.out.println(i);
	}
	// 静态变量
	static int i = 1;
	// 静态方法
	public static void m1() {
		System.out.println(i);
	}
	// 静态语句块/静态代码段
	static {
		System.out.println(i);
		System.out.println("静态语句块2");
	}
}

1.4.4 实例语句块
实例语句块
语法 : {
java代码;
}
实例语句块等同于成员方法,只是没有名字
执行顺序 : 静态语句块 > main方法 > 实例语句块(需要new对象 才会执行)

package com.demos02;
/**
 * 	执行结果:
 * 	静态语句块1
	静态语句块2
	main
	实例语句块1com.demos02._02_Static@15db9742
	实例语句块2
	构造方法
	实例语句块1com.demos02._02_Static@6d06d69c
	实例语句块2
	构造方法
 * 
 * 静态语句块属于类加载阶段,先执行静态语句块
 * 再执行main
 * main中有两个实例化对象,都是_02_Static()每次实例化对象地址不同,开辟新的空间地址。依次运行完实例化后的实例语句块
 * 
 * 
 * 
 * 
 * */
public class _02_Static {
	// 实例语句块
		{
			System.out.println("实例语句块1"+this);
		}
		{
			System.out.println("实例语句块2");
		}
		// 静态语句块
		static {
			System.out.println("静态语句块1");
		}
		static {
			System.out.println("静态语句块2");
		}

		public static void main(String[] args) {
			System.out.println("main");
			// 如果不实例化 实例语句块不执行,并且实例化几次,就执行几次
			new _02_Static();
			new _02_Static();
		}
		// 构造方法
		_02_Static(){
			System.out.println("构造方法");
		}

}

1.4.5 静态调用
静态调用,使用类名调用

那么可以使用对象调用吗? 可以

package com.demos02;

/**	静态方法m1
	成员方法m1
	静态方法m1
	静态方法m1
*		
*
*	简单理解 static 数据一眼 地址没有发生变化jvm自动把对象引用变量改成类名所以地址都是一样的,
*	成员可以一样可以不一样,实例化对象后,地址都会不一样
*
*/
public class _03_Static {
	public static void main(String[] args) {
		_03_Static.m_2();
		// 不能使用类名调用成员属性
		// _03_Static.m_1();

		_03_Static s = new _03_Static();
		s.m_1();
		// 静态方法也可以使用对象调用,因为在编译阶段,就会把对象引用变量转换为对应的类名去调用
		s.m_2();

		s = null;
		// 空指针异常
		// s.m_1();
		//
		
		// 可以调用,默认把s转化成_03_Static
		s.m_2();
	}

	public void m_1() {
		System.out.println("成员方法m1");
	}

	public static void m_2() {
		System.out.println("静态方法m1");
	}
}

1.4.6 静态和成员的区别以及应用场景
变量分类 :
静态变量 : 类中使用static修饰
成员变量 : 类中非static修饰
局部变量 : 方法中声明的变量是局部变量,作用域让当前方法使用

初始化时机 :
静态变量 : 类加载阶段初始化
成员变量 : 创建对象的时候初始化(构造方法)

应用场景 :
静态变量 : 类级别的,是所有对象共享的,比如一个静态变量 age = 18 ,那么说明所有对象都有这个age属性,并且值都是18
所有对象共有的属性和值
成员变量 : 对象和对象之间有相同的属性,但是可能有不同的值,非对象共享

package com.demos02;

public class _04_Static {
	public static void main(String[] args) {
		Student s1 = new Student(18, "张三");
		Student s2 = new Student(18, "李四");
		System.out.println(s1.age+" : "+s1.name);//18 : 张三
		System.out.println(s2.age+" : "+s2.name);//18 : 李四
		
		Student.addr="石家庄";
		System.out.println(Student.addr);//石家庄
		// 静态是对象共享数据,即使使用对象去访问,编译时也会转换为类名去访问
		s1.addr="河北";//static 引用地址相同
		System.out.println(s1.addr);//河北
		
		System.out.println(s2.addr);//河北
		
		s1.age = 19;//地址不同
		System.out.println(s1.age);//19
		System.out.println(s2.age);//18
	}
}
class Student{
	int age;
	String name;
	static String addr;
	
	public Student(int age, String name) {
		this.age = age;
		this.name = name;
	}
	
}

1.5 封装

封装是把对象的所有组成部分组合在一起,封装使用访问控制符将类的数据隐藏起来,控制用户对类的修改和访问数据的程度。
作用
适当的封装可以让代码更容易理解和维护,也加强了代码的安全性。

1.5.1 软件包机制
1.5.1.1 package
目标 : 当前文件的编译和运行

软件包机制 :
1 为了解决类的命名冲突问题
2 在java中使用package语句定义包
3 package语句只能出现在java源文件中的第一行
4 包命名通常采用公司域名倒叙
5 package限制的是class文件的放置位置(编译之后,把class文件放到哪里去)
com.tledu.oa.system
以上包命名可以体现出来 : 这个项目是天亮教育开发的OA项目,当前处于OA项目中的system模块
6 完整的类名 是带有包名的
7 带有包名的文件,编译应该是这样
javac -d 生成路径 java源文件路径
javac -d ./ -encoding utf-8 _01_Package.java
8 运行
java 包名.类名

什么是文件名 : 能够找到这个文件的全路径

在这里插入图片描述
import

package com.demos03;

public class _01_Package {
	public static void main(String[] args) {
		// 使用当前包下的类的时候,可以直接写类名也能找到
		A.m1();
		// 使用非当前包下的类中属性的时候,必须写类全名(包名.类名) 才能找到
		com.demos03.com.B.m1();
	}
}

package com.demos03;

import java.util.Date;

import com.demos03.com.*;

//导入静态属性 需要加static
import static com.demos03.com.C.*;
import static com.demos03.com.B.age;
public class _02_Package {
	public static void main(String[] args) {
		B.m1();
		C.m1();
		Date date = new Date();
		System.out.println(date);
		// 调用其他类中的静态属性的时候,必须要加类名
		System.out.println(B.age);
		// import static com.demos03.com.B.age; 导入静态属性后 可以直接使用
		System.out.println(age);
		//import static com.demos03.com.C.*
		m1();
	}
}

导入该类中所有的静态属性(静态变量/静态方法),让当前类可以不加前缀,直接调用
import static com.demos03.com.C.*;

import :
1 引入其他需要的类
2 只能出现在package语句执行,class语句之上
3 java核心类不需要导入,可以直接用,其他都不行
java.lang

语法 :
import 包名.类名; 导入单个类
import 包名.; 导入该包下所有的类

注意 : eclipse编程过程中,按空格的时候 会自动导包,如果程序没问题,但是报错,可以查看是不是包导错了

导入该类中所有的静态属性(静态变量/静态方法),让当前类可以不加前缀,直接调用
import static com.demos03.com.B.age;
不建议这样使用,在当前类中,不容看出来,这个变量是谁的变量

1.5.2 权限修饰符
在这里插入图片描述
private 私有化权限修饰符 ,除了自己(当前类)之外,都不能访问

public 公共的权限修饰符 , 谁都能访问

不写权限修饰符的时候 : 要么当前类中使用,要么当前包中使用

protected 受保护的权限修饰符 , 要么同类,要么同包,要么有继承关系

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值