Java听课笔记7(面向对象 上)

课程目录

  1. 面向对象的基本概念
  2. 类和对象
  3. 类和对象的定义格式
  4. 对象与内存分析
  5. 封装性
  6. 构造方法
  7. this关键字
  8. 值传递与引用传递
  9. 对象的一对一关系
  10. static关键字
  11. main方法分析
  12. 代码块
  13. 单例设计模式
  14. 对象数组与管理

1.面向对象基本概念

面向对象思维方式:先整体后集体先抽象后具体。
如何学习面向对象:
1.掌握一门面向对象语言的语法
2.熟悉面向对象的设计原则
3.熟悉慢性单纯的设计模式

2.类与对象

什么是类?
1.类是:分类 类别
2.通过分类,我们可以区别不同的事物种类,在日常生活中,我们常常这样做
3.所以,类是一组具有相同特性(属性)与行为(方法)的事物集合

类与对象的关系
1.类表示一个共性的产物,是一个综合的特征,而对象,是一个个个性的产物,是一个个个体的特征。
2.类由属性和方法组成
属性:就相当于一个个的特征
方法:就相当于人的一个个行为,例如:唱,跳,rap,蓝球

3.类和对象的定义格式

定义一个类

class类名称{
属性名称;
返回值类型 方法名称(){}

对象的定义:
一个类要想真正的进行操作,则必须依靠对象,对象的定义格式如下:

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

在Java中,对象声明有两种含义

声明对象:Horse horse=null;

表示声明了一个对象,但是此对象无法使用,horse没有具体的内存指向

实例化对象:horse=new Horse();

//表示实例化了对象,可以使用
按照以上方式就能产生对象了

如果要想访问类中的属性或者方法(方法的定义),
可以依靠以下的语法形式:
访问类中的属性

对象 . 属性;

调用类中的方法:

对象 . 方法();

通过对象调用方法:

horse.eat();

匿名对象调用方法
new Horse().eat();

package test;

public class test{
	public static void main(String[] args){
		Horse h=null;//声明一个变量(除了八种基本数据类型外,都是引用数据类型,包括数组)
		
		//创建一个Horse类型的对象,实例对象
		h=new Horse();
		//有了对象,我们就可以调用对象的属性和方法
		h.name="赤兔马";
		h.age=30;
		
		h.run();//调用方法,那么方法就会被执行。
		h.eat();                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
		
		//匿名对象,只能使用一次,用完后,该对象就会被释放
		new Horse().eat();
		
		h=null;//把对象释放
		//h.eat();//当对象不存在时,调用该对象的属性和方法将报错(空指针)
	}
}

//自定义一个类(类型)
class Horse{
	//在类中定义属性
	String name;
	int age;
	public void run(){
		System.out.println("马跑步"+name);
	}
	public void eat(){
		System.out.println("我吃草");
	}
	
}

4.对象内存分析

1.new关键字表示创建一个对象
2.new关键字表示实例化一个对象
3.new关键字表示申请 内存空间

注意:如果使用一个没有申请内存空间的对象,会报空指针异常

java.lang.NullPointerException
栈内存存放类型名,存放基本数据类型
堆内存存储对象用的
在这里插入图片描述
1.在栈内存中存个变量名
2.语句二表示在堆内存中new一块区域用来存放属性和方法,并把地址存在栈内存中

在这里插入图片描述
注意,此时“小白”仅仅是地址,2这样写是为了方便看。
在这里插入图片描述
在这里插入图片描述
声明两个对象,一个实例化一个没有实例化
在这里插入图片描述
对象之间的赋值
在这里插入图片描述
注意:如果我更改了horse1.name,那么horse2.name也会改变,同理也是这样。因为他俩指向同一个内容
在这里插入图片描述
注意:当horse2=horse1;后对horse2.name改,horse1.name也会改,因为指向的地址相同。

类与对象小结

  1. new关键字:表示向内存申请空间,也表示实例化一个对象,创建一个对象。
  2. 一个对象在内存中的大小,由该对象的所有属性所占的内存大小的总和,引用类型变量在32位系统上占4个字节,在64位系统上占8个字节加上额外的对象隐形数据所占的大小。(String字符串是引用类型变量,不是基本数据类型变量
  3. 相同的类型才可以赋值
  4. 不同的引用,指向同一个对象,任何一个引用改变对象的值,其他引用都会反映过来
  5. 当一个堆中的对象没有被任何引用变量所指向时,该对象会被JVM的GC程序认为是辣鸡对象,从而被回收。
  6. 编程时要注意的问题:在确定不使用对象时,要尽早释放对象:引用=null//匿名对象,只能使用一次,用完后,该对象就会被释放如:

new Horse().eat(); h=null;//把对象释放

5.封装性

封装性的概念
1.封装性是面向对象思想的三大特征之一。
2.封装就是隐藏实现细节,仅对外提供访问接口
封装有:类的封装,属性的封装,方法的封装,组件的封装,模块化封装,系统级封装…

封装的好处
1.模块化
2.信息隐藏
3.代码重用
4.插件化易于调试
5.具有安全性

封装的缺点会影响执行效率

package test;

public class test{
	public static void main(String[] args){
		//未封装之前,可以直接调用
		Person p1=new Person();
		p1.name="feifei";
		p1.age=18;
	}
}

/*封装性*/
//没有封装之前
class Person{
	//属性的封装
	String name;
	int age;
}

如果属性没有封装,那么在本类之外创建对象后,可以直接访问属性
private关键字:访问权限修饰符,public表示共有的,private表示私有的。私有的属性或者方法,只能在本类中访问,共有的属性或者方法,可以被类外的其他类访问。想要早类外部访问私有属性,我们需要提供共有的方法来间接访问
通常在一个类中,属性都私有化,并对外体提供getter and setter 方法

封装后

class Person{
	//加上private,封装属性
	private String name;
	private int age;
}

//未封装之前,可以直接调用
Person p1=new Person();
p1.name=“feifei”;
p1.age=18;

想要类外部访问私有属性,我们需要提供共有的方法来间接访问

//封装之后调用
Person p1=new Person();
p1.setName(“feifei”);
p1.setAge(18);

package test;

public class test{
	public static void main(String[] args){
		//封装之后调用
		Person p1=new Person();
		p1.setName("feifei");
		p1.setAge(18);
	}
}

/*封装性*/
//没有封装之前
class Person{
	//属性的封装
	private String name;
	private int age;

//getter and setter
//对外提供一个为name属性设值方法
public void setName(String name){
	this.name=name;//等号后面的name为括号内参数name,this后name为class的属性name
	
}
//对外提供一个获取name属性的方法
public String getName(){
	return name;	
}
public void  setAge(int age){
	this.age=age;
}
public int getAge(){
	return age;
	
	}
}

在这里插入图片描述

6.构造方法

什么是构造方法

构造方法的定义
构造方法是在类中定义的,构造方法的定义格式:方法名称与类名称相同,无返回值类型的声明:

public Dog();{}

对象的实例化语法:

Dog dog=new Dog(); //Dog后面有个括号,带括号表示调用了方法,此时调用的方法就是构造方法了

1.构造方法就是类构造对象的时候调用的方法,用于对象的初始化工作
2.构造方法是实例化一个类的对象时,也就是new的时候,无需像普通方法对象名.方法名。最先调用的方法。
3.新手在刚开始
很容易将class定义到main函数中
*。造成Java出现No enclosing instance of type E is accessible. Must qualify the allocation with an enclosing

构造方法的调用:

Dog dog =new Dog();
//new的过程中默认调用了dog()构造方法;
Dog dog1=new Dog(“旺旺”,18);

package test;

import java.util.Arrays;
import java.util.Random;

public class test2 {
	public static void main(String[] args) {
		Dog dog =new Dog();
		//new的过程中默认调用了dog()构造方法;
		Dog dog1=new Dog("旺旺",18);
	}

}
//构造方法是在类中定义的;/
	class Dog {
		// 方法名称与类名称相同
		// 注意:无返回值类型的声明,不要写void
		//无参构造方法为默认,可以不写,前提是后面还有构造方法
		public Dog() {
			System.out.println("构造方法已经调用了");
		}
		//重载构造方法,无返回值类型声明,不写void
		public Dog(String name,int age){
			this.name=name;
			this.age=age;
			System.out.println("带两个参数的构造方法执行了");	
		}
		private String name;
		private int age;
		public void setName(String name){
			this.name=name;
			
		}
		public String getName(){
			return name;
		}
		public void setAge(int age){
			this.age=age;
		}
		public int getAge(){
			return age;
		}
	}

构造方法的重载
无参构造方法:
public Dog(){}
带一个参数的构造方法:
public Dog(String name){
this .name=name;
}
带多个参数的构造方法:
public Dog(String name,int age){
this .name=name;
this.age=age;
}

构造方法A如何调用构造方法B
this(方法B名字);
在这里插入图片描述
构造方法小结
在这里插入图片描述

7.this关键字

在Java基础中,this关键字是一个非常重要的概念。使用this关键字可以完成以下操作:

  • 调用类中的属性
  • 调用类中的方法或构造方法
  • 表示当前对象

调用类中的属性
谁调用我,谁就是当前对象。谁就是this,代码中是cat在这里插入图片描述
调用类中的方法或构造方法在这里插入图片描述
补充:this前面可以加上类名.this。在后面的内部类知识中可能会涉及到。

8.值传递和引用传递

知识回顾:成员变量与局部变量的区别
示例一:值传递

package test;

public class test2 {
	public static void main(String[] args) {
		int x = 10;
		method(x);
		System.out.println("x=" + x);
	}

	public static void method(int mx) {
		mx = 20;
	}
}

运行结果X=10;为啥不是20呢
在这里插入图片描述
因为x和mx 都是在方法中定义的,都存储在栈内存中,只是mx被赋值成了20。 Java都是值传递。X并没有变化
示例二:引用传递

package test;
public class test2 {
	public static void main(String[] args) {
		Duck d=new Duck();
		menthod(d);
		System.out.println("鸭子的年龄是"+d.age);;
	}
	public static void menthod(Duck duck){
		duck.age=5;
	}
}
class Duck{
	int age=2;//省略封装
}

运行结果:鸭子的年龄是5,在这里插入图片描述注意,new操作后,栈内存存的是d的地址、且class Duck后存的是成员变量,放在对内存中
当变量存的是地址的时候,操作就是引用传递。
当变量存的是值的时候,操作就是值传递。
示例三:String类型传递

package test;
//字符串本身就是一个对象
public class test2 {
	public static void main(String[] args) {
		String name ="小飞";
		method(name);
		System.out.println("名字是"+name);
	}
	public static void method(String sname){
		sname="小贝";
		
	}
}

String的值储存在堆内存当中,一个字符串相当于new一个对象出来。字符串本身就是一个对象
在String 中有两个对象出现。”“小飞”和“小贝”在这里插入图片描述
示例四:还是String传递

package test;
public class test2 {
	public static void main(String[] args) {
		Person p=new Person();
		menthon(p);
		System.out.println("人名是"+p.name);
	}
	public static void menthon(Person per ){
		per.name="贝贝";
	}
}
class Person{
	String name ="飞飞";//省略封装
}

输出结果:人名是贝贝
注意:String是引用型数据变量,String name 表示在堆内存中开辟一块内存存储的是name的地址。=“飞飞”表示在这块地址上命名
在这里插入图片描述
除了基本数据类型在栈内存完成之外,其余的都在堆内存完成。
自己画图画几遍

9.对象的一一对应关系

两个对象之间一一对应关系:
比如:
一个英雄(hero)对一个兵器(weapon)代码如何表示?

补充说明
要注意Weapon weapon和 Weapon wepon = new Weapon() 的区别

前面讲的是声明一个变量,变量名为weapon,变量类型为Weapon 后面讲的是创建一个Weapon 对象,并把它赋给了变量wepon。也就是说wepon 实际上引用了一个Weapon 类型的对象
其实类名不是作为数据类型,只能说将这个类的对象作为返回值。意思就是说,这个方法的返回值不是普通的数据类型,而是一个类对象。这样做可以避免一个方法要返回N多的数据,比如说,你要同一个方法中得到name和age,但是java又不能返回多个值,除了可以使用一个字符串或者字符串数组存放外,我们可以定义一个Student对象,对象中包含name和age属性,这样就可以用这个对象把属性封装起来以及方法,一起返回。

1.在hero类定义一个Weapon类型的weapon ,(在本类中定义一个对方方法)
2.设置weapon的getter and setter方法,单项一对一,若双向可在weapon类同样设置
3.关联起来

//双向一对一,英雄得到他的兵器,反过来兵器也能得到他的英雄
//单向一对一,英雄捡到兵器,兵器不知道英雄
package test;
public class test{
	
	public static void main(String[] args){
		Hero hero =new Hero("刘备",18);
		Weapon weapon=new Weapon("剑",3);
		//把两个对象关联起来
		hero.setWeapon(weapon);
		weapon.setHero(hero);
		String name=hero.getName();
		int age=hero.getAge();
		Weapon w=hero.getWeapon();
		System.out.println("我是"+name+",我"+age+"岁,武器是"+w.getName()+",等级是"+w.getGrade());
	}

百度谷歌了一下相关资料。原来我写的内部类是动态的,
也就是开头以public class开头。
而主程序是public static class main。
在Java中,类中的静态方法不能直接调用动态方法。
只有将某个内部类修饰为静态类,然后才能够在静态类中调用该类的成员变量与成员方法。
所以在不做其他变动的情况下,
最简单的解决办法是将public class改为public static class.

//通过英雄来获取它的信息
//英雄类

public static class Hero{
	private String name;
	private int age;
	private Weapon weapon;//在本类中定义一个其他类类型的私有变量
	//一对一对应关系
	//设置getter and setter方法
	public void setWeapon(Weapon weapon){
		this.weapon=weapon;
	}
	public Weapon getWeapon(){
		return weapon;
	}
	public Hero(){}
	public Hero(String name,int age){
		this.name=name;
		this.age=age;	
	}
	public void setName(String name){
		this.name=name;
	}
	public String getName(){
		return name;
	}
	public void setAge(int age){
		this.age=age;
	}
	public int getAge(){
		return age;
	}
}

//武器类

public static class Weapon{
	private String name;
	private int grade;
	private Hero hero;//设置Hero类型的hero;
	//设置getter and setter 方法
	public void setHero(Hero hero){
		this.hero=hero;
	}
	public Hero getHero(){
		return hero;
	}
	public Weapon(){}
	public Weapon(String name,int grade){
		this.name=name;
		this.grade=grade;
	}
	public void setName(String name){
		this.name=name;
	}
	public String getName(){
		return name;
	}
	public void setGrade(int grade){
		this.grade =grade;
	}
	public int getGrade(){
		return grade;
	}
	}
	
}

10.static关键字

static关键词的作用:
1.使用static关键词修饰一个属性
声明位static的变量实质上是全局变量(生命周期变长了,从程序启动到程序结束)
2.使用static关键字修饰一个方法
通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法
3.使用static关键字修饰一个类(普通类不能用static,只有内部类才能用static)

static关键字总结
1.静态对象或方法不属于对象,依赖类。
2.静态变量是全局变量,生命周期从类被加载后一直到程序结束
3.静态变量只有存一份,在静态方法区存储
4.静态变量是本类所有对象共享一份
5.建议不要使用对象名去调用静态数据,直接使用类名调用
6.static修饰一个方法,那么该方法属于类,不属于对象,直接用类名调用。意味着没有创建对象也能用
7.静态方法不能访问非静态的数据,只能访问静态。this和super都无法出现在static 修饰的方法中

package test;
public class test{
	
	public static void main(String[] args){
		//Role beibei=new Role("刘备","蜀国");
		//Role yuanchuang =new Role("云长","蜀国");
		//Role feifei =new Role("张飞","蜀国");
		
		Role beibei=new Role("刘备");
		Role yuanchuang =new Role("云长");
		Role feifei =new Role("张飞");
	
		System.out.println(beibei.getInfo());
		System.out.println(yuanchuang.getInfo());
		System.out.println(feifei.getInfo());
		
		System.out.println("-------静态变量是本类所有对象共享一份-------");

		beibei.country="晋朝";
		System.out.println(beibei.country);
		System.out.println(yuanchuang.country);
		System.out.println(feifei.country);
		
		System.out.println("-------建议不要使用对象名去调用静态数据,直接使用类名调用-------");
		
		beibei.country="汉朝";
		System.out.println(Role.country);//因为country是静态属性,所以可以用类名点属性
		System.out.println(Role.country);
		System.out.println(Role.country);}
} 

//角色

class Role{
	private String name;
	//private String country;不想写三个蜀国所以:
	static String country="蜀国";//静态变量(全局变量)
	public Role(String name,String country){
		this.name=name;
		this.country=country;
	}
	//去掉country,可行
	public Role(String name){
		this.name=name;
	}
	public void setName(String name){
		this.name =name;
	}
	public String getName(){
		return name;
	}
	//静态方法不能访问非静态的数据
	public static void setCountry(String country){
		//this.country=country;
		//Cannot use this in a static context
		//意思是:this关键字不能在static静态方法中使用,具体解释看下文
		
		Role.country=country;
	}
	public String getInfo(){
		return "名字:"+name+",国家:"+country;
		
	}
}

方法加了static,就会有静态方法区
在这里插入图片描述

Cannot use this in a static context 因为:

Static方法是类方法,先于任何的实例(对象)存在。即Static方法在类加载时就已经存在了,但是对象是在创建时才在内存中生成。而this指代的是当前的对象

举个例子:

public class Test {
    private static int n = 0;
	public static void setNum(int n) {
		this.n = n;  //Cannot use this in a static context
	}
	public static void main(String[] args) {
		setNum(0);
	}
}

在方法中定义使用的this关键字,它的值是当前对象的引用.也就是说你只能用它来调用属于当前对象的方法或者使用this处理方法中成员变量和局部变量重名的情况.

而且,更为重要的是this和super都无法出现在static 修饰的方法中,static 修饰的方法是属于类的,该方法的调用者可能是一个类,而不是对象.如果使用的是类来调用而不是对象,则 this就无法指向合适的对象.所以static 修饰的方法中不能使用this.

在这里插入图片描述
声明为static的方法有以下几条限制:

  • 它们仅能调用其他static方法
  • 它们只能访问static数据
  • 它们不能以任何方式引用super或this

所有对象共同的属性或者方法,那么我们可以定义为静态的。

11.main方法分析

主方法:
public static void main (String[ ] args){
//代码块
}
public:公有的,最大的访问权限
static:静态的,无需创建对象
void:表示没有返回值,无需向jvm返回结果
main:方法名,固定的方法名
String[ ] args:表示参数位字符串数组,可以在调用方法时传入参数

12.代码块

  1. 普通代码块
    直接写在方法中的代码块就是普通代码块
  2. 构造块
    是在类中定义的代码块,new创建对象时即被调用(构造方法也是new后即调用),优于构造方法执行
  3. 静态代码块
    在类中使用static声明的代码块称为静态代码块
    在第一次使用的时候被调用(创建对象),只会执行一次,优于构造块执行,我们在项目开发中,通常会使用静态代码块来初始化只调用一次的数据。比如说:读取配置文件
  4. 同步代码块(多线程中讲解)

小结:重点使用的顺序是静态代码块,普通代码块,同步代码块,构造代码块

package test;
public class test{
	
	public static void main(String[] args){
		Student s=new Student(); //构造块是在类中定义的代码块,
		//	new创建对象时即被调用优于构造方法执行
		System.out.println("-------------");
		Student s1=new Student();
	}
}

class Student{
	Student(){
		System.out.println("我是构造方法,顺序排第一,却最后执行");
 
	}
	
	{
		System.out.println("我是构造代码块,我排第二,我比构造方法先执行");
	}
	
		static{
			System.out.println("我是静态代码块,我排最后 ,但我第一个执行。只能执行一次");
		}
	public void study(){
		System.out.println("我是最普通的代码块");
	}
}

执行结果:
在这里插入图片描述

13.单例设计模式

单例设计模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

  1. 构造方法私有(private)化,里面什么都不要写
  2. 创建一个本类静态对象
  3. 给外部提供一个公共的静态的方法getInstance(),用来获取对象实例

两种实现方式:

  1. 饿汉式:在类被加载后,对象立马被创建,到程序结束后释放。占用内存时间长,效率高
  2. 懒汉式:在第一次调用getInstance方法时,对象被创建,到程序结束后被释放。占用内存时间短。效率低(懒加载,延迟加载)

代码:

package test;
public class test{
	public static void main(String[] args){
		Singleton1 s1=Singleton1.getInstance();
		s1.print();
		Singleton2 s2=Singleton2.getInstance();
		s2.print();

	}
}
//饿汉式:占用内存时间长,效率高
class Singleton1{
	//1.构造方法私有化,里面什么都不要写
	Singleton1(){}
	//2.创建一个本类静态私有化对象
	private static Singleton1 s=new Singleton1();
	//3.给外部提供一个公共的静态的方法,用来获取对象实例
	public static Singleton1 getInstance(){
		return s;
	}
	public void print(){
		System.out.println("测试用其他的方法1");
	}
}
//懒汉式:占用内存时间短。效率低(懒加载,延迟加载)
//在多线程访问时会有安全问题
class Singleton2{
	private Singleton2(){}
	//懒,并没有定义对象出来
	private static Singleton2 s;
	
	public static Singleton2 getInstance(){
		if(s==null){
			s=new Singleton2();
		}
		return s;
		
	}
	public void print(){
		System.out.println("测试用其他方法2");
	}
	
}

在项目中为什么要使用单例,单例有什么好处?

  1. 在设计一些工具类的时候(通常工具类,只有功能方法,没有属性)
  2. 工具类可能会被频繁调用
  3. 可以节省重复创建对象所带来的内存消耗,从而提高效率

能不能使用构造方法私有化+静态方法来替代单例?
格式:在这里插入图片描述
如果使用构造方法私有化+静态方法来实现工具类。那么静态方法会存在方法区,加载之后就会存在,调用方便
如果使用构造方法单例,方法是普通方法,依赖对象实现。运行过程中如果方法中有参数需要进栈出栈。内存占用小。

14.对象数组与管理

点击鸡舍管理系统

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TVART郭术生C4D学习笔记-四部曲全能班是一款全面入门C4D的课程,通过四个阶段的学习,可以轻松掌握C4D软件的基础知识和基本操作,并能够制作简单的3D场景和模型。 在第一部分中,学习者将会了解到C4D的基本概念和软件界面结构,如何创建和编辑3D对象、设置材质、光源和相机,以及如何导入和导出场景文件。同时,还包含了一些实例的制作,使学习者可以亲手尝试制作一些基础的3D模型。 在第二部分中,介绍了C4D中的变形工具、建模方法和物体分层等高级技能,并有更多的实例演示。学习者可以学习如何使用模型图形和建模工具,进行更加复杂的3D建模。 在第三部分中,学习者将深入掌握C4D中的动画制作技能,包括如何创建关键帧动画、运动路径动画、变形动画等等,并在实例中加以演示。 最后,在第四部分中,学习者学习到了C4D中的电影与视频制作、逼真的渲染技术、动力学建模以及摄像机动画技巧等更为高级的技术。在本部分中,学习者将会制作更为复杂的3D模型和场景,并在其中加入比较真实的材质和照明效果,在此基础上创建自己的作品。 总的来说,TVART郭术生C4D学习笔记-四部曲全能班是一款非常全面和实用的C4D教程,从基础到高级的技能都有所覆盖,并且每个部分都有很多实例演示,使学习者更加容易理解和掌握。对于想要入门3D制作和动画的人来说,这是一份非常不错的学习资料。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值