2021-05-16 java基础 内存分配 面向对象

27 篇文章 0 订阅

2021-05-16
java笔记
一、数组
1.一维数组的动态定义: int [] li = new int [4]
2.一维数组的静态定义:int [] li = new int []{1,2,3,4}
3.int数组里的默认初始值为0,在对象中默认初始值是null
4.二维数组的静态定义:int[][] li =new int [][] {{1,2,3},{3,4,5}}
5.二维数组的动态定义:int[][] li =new int [2][3]
5.二维数组的动静态定义: int[][] li = new int [2][] 一维定义二维不定义
6.特殊写法:int[] x,y[]; x是一维数组y是二维数组;
7.循环读二维数组;

for(i=0;i<arr.length;i++){
	for(j=0;j<arr[i].length;j++){
		:内容
	}
	}

8.空指针异常:int[] arr=null; 取arr[0] 就会报错;
9.(1):length方法用于获取数组的长度。
(2):length()用于获取String字符串中字符的个数
二、面向对象编程

1.类:属性(成员变量 ),方法(函数)。
2.修饰符:
private 属性: 该属性只能由该类的方法访问,
public 属性: 该属性可由其他类以外的方法访问
3.变量
(1) 成员变量:在方法体外,类体内声明的变量,
(1.实例变量:不以static修饰的

在类实例化成对象后才能用
在类中
public string sex ="男"
在调用时
Personl p = new Personl()
p.sex;

(2.类变量:以static修饰

在类声明添加static 
public static sex = "男"
在调用时
personl.sex
可以直接用

(2) 局部变量:在方法体内声明的变量,
(1.形参:方法签名中定义的变量

public void move (string sex) 
这里的sex时形参

(2.方法局部变量:在方法内定义

public void move (string sex)
int a;
这里的a时方法局部变量

(3.代码块儿局部变量:在代码块儿定义

在类里面直接写一个大括号叫代码块
public class personl{
{
	这里的变量时代码块儿变量
}
}

补:(1.实例变量只能是在类实例化后的的对象中使用
(2.可直接写public string name;这里的name是默认值null
(3.局部变量存在于栈内存中
(4.局部变量不能 int k;必须赋值
(5.在这里插入图片描述
4.方法
(1.通过类实例化出来的对象可以多个

类
public class personl{

}
personl p1 = new personl
personl p2 = nwe personl
实现类出两个实例化对象p1 p2 还可以有多个
每个对象都是独立的互不干扰;

(2.方法只有在被调用时才会被执行;
(3.在class中写的方法中的形参,可以咱本class中直接调用
(4.方法中可以调用方法,但不可以在方法中定义方法
(5.在同一个类中,所有的方法可以互相调用,不用new去实例化

5.对象
在这里插入图片描述
引用类型中,string 类型初始值是null int类型是0
(1.匿名对象:

不定义对象的句柄,直接调用对象的方法
new personl().shout()  //personl为类名

~如果对象只需要调用一次,那么可以使用匿名对象
~匿名对象经常是作为实参传递给方法调用

public void personl(int i,int j,int k)
其中i,j,k为实参

(2.写这static修饰的变量只能访问带有static类型的变量,不能访问普通类型的;

5.方法(函数)重载
(1)在一个类中允许存在一个以上同名个方法,只要他们的参数,参数类型不同 ,顺序不同也可以
例如:

public int add(int x,int y){
}
public double add(int x,double y)
{}
public int add(int x,int y,in z)
{}

调用方法:

person1 t4 = new person();
t4.add(2,3)
t4.add(2,3.4)
t4.add(2,3,4)

6.方法可变参数传参
(在不知道需要传递多少个参数时使用)
(1)用数组来传递可变参数

public void test(int a,String [] str1)
{
	for(i=0;i<str1.length;i++)
		System.out.println(str1[i]);
} 
main中
person1 p3 =new person(); 
//新建一个数组,将数组中的值,传入打方法中;
String[] str =new String[]{"gaoxiuqi","guolinyu","ai"};
p3.personInfol(str);

(2)用Java特有的…来传递可变参数

public void test(int a,String... str1)
{
	for(i=0;i<str1.length;i++)
		System.out.println(str1[i]);
} 
main中
person1 p3 =new person(); 
//这里可以直接传值

p3.personInfol("gaoxiuqi","guolinyu","ai");

(2)
->对于第一种的数组传入时,不能传入参数为空,最少也需要传入null
->对于第二种的…传入时,可以直接不写直接为空;
->public void test(String... str1,int a)这种是错误的方式 可变参数必须放在最后;

7.方法的参数传递
(1)形参:方法声明时的参数

public void add(String a,int b)
这里的a b为形参;

(2)实参:方法调用时实际传递给形参的参数值
(3)java里方法的参数传递方式只有一种,值传递。即实际参数的值的副本(复制品)传入方法内,而参数本身不受影响。
(4)在这里插入图片描述
(1.
->栈stack中基础数据类型是例如 int,String,double,float……等等。还存放这对象的地址,
->堆heap中存储所有对象
->方法区method存放的都是方法class,static变量
例子:

public class DataSwap{
public int a;
}

在这里插入图片描述

public static void swap(DataSwap dsl){
dsl.a = 6;
System.out.println("在swap方法中,dsl.a的值是:"+ds.a);
}
public static void man(String[] args){
DataSwap ds = new DataSwap();
System.out.println("调用swap方法之前,ds.a的值是:"+ ds.a);
swap(ds);
System.out.println("调用swap方法之后,ds.a的值是:"+ ds.a);

}
}

这个输出一次是0,6,6,其中修改ds1的值,ds的值也被修改,这里因为ds,ds1是被存放在栈中,对象实际地址实在堆中,ds,ds1都是指向堆的地址,所以ds1,和ds改变的是堆中的同一个方法(ds叫引用对象)

在这里插入图片描述
(2.总结
在这里插入图片描述
8.软件-包
(1)关键字——packbage
(2)包类可以理解为文件夹,有层级结构(包下的包是有点分割)例如,com.test com包下层有个test包
(3)调用时需要加

import day06.test.person;

在class上面指名调用哪里的person类,(原因不用包里可以有同一个名字的类)(不同的包可以有相同的文件)
在这里插入图片描述
也可以这么写

day06.test.person p= new day06.test.person();

在不知道需要用到包里的哪个class时
再可以用

import day06.test.*;//day06文件下的test文件下的所有class(学后面后的补充)

直接引用这个包下所有java文件
(4.同一个包下不用写import day06.test.文件

9.封装和隐藏
(1.把变量(属性)设置为私有private,然后再把变量(属性)用公共的方法进行设置,
(2.方便加入逻辑控制;增强代码可维护性
(3.例如;

public class person{
	private int age;//对属性(变量进行私有化)
	public void setAge (int a)//对属性进行封装隐藏
	{
		if(age <100 && age>0age=a;
		else
			System.out.println("输入无效,请输入0~150之间的数");
	}
	public int getAge()
		return age;
}

public class person1{
	public int main()
	{
		int a=0;
		person p = new person();
		p.setAge(23);
		a=p.getAge//获取到了age
	}
}

10.四种访问权限修饰符
属性(变量)的修饰符
(1)private:只能再本类中使用
(2)(缺省):同一个包下可以使用
(3)protect:同包下,子类都可用
(4)public:都可用
class的修饰符
(1.public:
(2.default(缺省):同包下使用
在这里插入图片描述
下面的可以调用上面的
在这里插入图片描述
(5)
->子父类在同一个包下,缺省、protected、public都可以用来修饰的成员变量
->子父不在同一个包下,只能用protected、public来修饰的成员变量

11.父子类

12.构造器(构造方法)
(1.new的根本原理:通过类的构造方法
(2.java语言中每个类至少都有一个构造器
(3.默认构造器的修饰符与所属类的修饰符一致
(4.一旦定义了构造器,则系统不再提供默认构造器
(5.一个类可以创建多个重载的构造器
(6.父类构造器不可被子类继承
例如:

public class person3{
/**
*这里是构造器,可传值可不传值;
*也可以不写,Java会有默认的构造器,写了就是用写了的
**/
	public person3 (int c,String d){//这里是构造器
		c=a;
		d=b;
	}
	int a;
	String b;
}

public class person{
	public static void main(String[] args){
	person3 p5 = new person3(2,gao);//这里可以直接向类中传递值
	}
	
}

13.构造器(也叫构造方法)的重载
(1.重载的多个构造方法就相当于提供了多个初始化new对象的模板
(2.
例如:

public class person3{
/**
*构造器的重载
*可以有多个构造方法
**/
	public person3 (int c);
	public person3 ();
	public person3 (int c,String d){//这里是构造器
		c=a;
		d=b;
	}
	int a;
	String b;
}

14.关键字——this
(1.this() 使用时必须放在方法或构造器的首行;
(2.this不能出现自己调自己,或者间接的通过某个方法或构造器
调用自己
例如:

//this()这意思是调用构造器
public class person{
	public person(int age,String name){//构造器
		this.age=age;//this.age是成员变量,是下面的int age
		this.name=name;
	}
	public  person(){//不能自己调自己是说此时在上面的构造器中不能写this()(意思是下面的调用上面的,上面的再调用上面的,就间接自己掉自己了)也不能写this(2,"name")(这里是直接掉自己了)
		this(1,“name”);//这里是调用上面的构造器person
	}
	int age;
	String name;
	public void person1(int age){
		this.age=age;//与上同
	}
	
}

15.javaBean(逻辑上的一种约定俗称的写代码规则)
(1.例如:

public class person{
	private int age;//这里的属性必须用私有的private
	private String name;
	public void setAge(int age){
		this.age=age;
	}
	public int getAge(){
		return this.age;
	}
	public void setName(String name){
		this.name=name;
	}
	public int getName(){
		return this.Name;
	}
}

除了用手一个一个敲还有可以写好属性直接生成方法get和set

public class person{
	private int age;
	private String name;1)写好属性
	(2)本class中鼠标右键找到Source
	(3)然后找到里面的GGS开头的三个字母
	(4)然后勾选出现的所有属性
	(5)点ok
}

16.继承
(1.在这里插入图片描述
在这里插入图片描述
(2.子类继承父类所有的属性方法,并增加子类特有的属性

public class Person{//父类
	public String name;
	public int age;
	public String getInof person {
	}
}
//子类
public class Student extends Person{//这里意思就是Student继承person的属性或方法
	public String school;
	//这里可以通过this.去调用,person中的属性
}

(3.把共性的东西抽取出来做父类,实际需求的子类在继承父类的基础上,写自己特有的代码!(父类,基类,超类)
(4.作用
->提高代码的复用性
->让类与类之间产生关系,提供多个态的前提
->不要为了某个类的功能而去继承(继承室友逻辑关系在里面的,不能随意继承)
->注意使用的修饰符需要对应,不能用private(私有的)
17.继承——细节
(1)一个子类只能有一个父类,一个父类可以派生出多个子类;(单继承)
在这里插入图片描述
18.方法的重写(override)
(1)重载和重写的区别:
->方法的重载:一个类可以有多个同名方法
->方法的重写:子类可以写父类的方法,覆盖父类的方法
(2)子类重写父类方法,只是重写编写方法体的代码
(3)如果父类的方法是public的,子类重写的时候就不能使用缺省和以下
(4)使用:

//父类
public class person{
	int age;
	public void student(int age){
		this.age=age;
	}
}
//这里可以用Alt+/ 选择对应的类里的方法自动生成重写的方法结构,生成的结构内部的东西可以删除,写自己的代码;
@override
public class person1 extends person{
	String name;
	public void student (String name ){
		this.name = name;
	}
}
//调用
public class person2{
	public static void  main (String args){
		person1 s1 = new person1();
		s1.age = 12;
		s1.student("gao");
	}

}

19.super
(1)super可以用于父类定义的方法,属性,构造器!
(2)子父类里面有同名成员时可用,super进行区分;
(3)super追溯的不仅限于父类,父类的父类等都可以
(4)子类中所有的构造器默认都会访问父类中的空参数的构造器
(5)当父类中没有空参数的构造器时,子类的构造器必须通过this(参数列表)或者super(参数列表)的语句指定调用本类或者父类中相应的构造器,且必须放在构造器的第一行;
(6)如果子类构造器中既没有显示调用父类或本类的构造器,且父类中又没有无参构造器,编译会出错;
(7)实例:

public class person{
	public int age;
	public String name;
}
//student 继承 person的属性
public class student extends person{
	super.age = 12;
	
}
//调用
public class testStudent{
	public void  main test(String{} args){
		student.s1 = new student();//这个是调用类
		
	}
}

上面(4)的验证:

public class person{
	//这个是父类构造器
	//目的验证子类构造器会调用父类默认的构造器
	public person(){
		System.out.println("子类构造器会调用父类默认的构造器")
	}
	public int age;
	public String name;
}

public class student extends person{
/**
*这里相当于
*public student(){
*	super();//这里必须放在首行
*}
*只不过省略了
**/
	super.age = 12;
	
}
//调用
public class testStudent{
	public void  main test(String{} args){
		student.s1 = new student();//这个是调用类
		
	}
}
//结果会输出:子类构造器会调用父类默认的构造器

验证(5)

public class person{
	//这个是父类构造器
	//目的验证父类中构造器没有空参的话,子类中必须也有一个不为空参的构造器,于父类对应;
	public person(int age ,String name){
		System.out.println("子类构造器会调用父类默认的构造器")
	}
	public int age;
	public String name;
}
//此时子类中也必须得有与父类对应的构造器
public class student extends person{
	public student(int sex,String name){
		super(sex,name);//这里必须得放在首行
	}
	super.age = 12;
	
}
//调用
public class testStudent{
	public void  main test(String{} args){
		student.s1 = new student();//这个是调用类
		
	}
}

20.this和super的区别
(1)
this / super | this | super
-------- | ----------|---------|---------
访问属性 | 访问本类中的属性,如果本类没有此属性则从父类属性中查找 | 访问父类中属性
调用方法 | 访问本类中的方法 | 直接访问父类中的方法
调用构造器 | 调用本类构造器,必须放在构造器首行 | 调用父类构造器,必须放在子类构造器的首行
特殊 | 表示当前对象 | 无此概念

->细节小贴士:由于this和super的都需要把用时都需要把他们放在首行,所以只能存在一个;

21.简单类对象的实例化
(1.问题:person p = new person()如何实例化的?
JVM在这里插入图片描述
过程:
(1.方法区:加载person.class
(2.栈内存:在栈中申请空间,声明变量p (p BE2500)
(3.堆内存:new person在堆内存中开辟空间、分配地址。(假如地址BE2500)
(4.堆内存:并在对象空间中,对对象中的属性进行默认初始化,此时age=0;name=null,sex=0,类成员变量显示初始化,此时age=1,name=“zhangsun”,sex=0(显示初始化:=右边向左边赋值)
(5.栈内存,构造函数的方法进栈,进行初始化
(6.栈内存,初始化完毕后,将堆内存中的地址赋值给引用变量,构造方法出栈;

22、子类对象的实例化
Student stu = new Student();实现过程:
在这里插入图片描述
过程
(1. 方法区:先加载父类person.class,再sstudent.class
(2.栈内存: 在栈中申请空间,声明stu
(3. 堆内存:在堆内存中开辟空间,分配地址。
(4.堆内存:并在对象空间中,对对象的属性(包括父类的属性)进行初始化。
(5.栈内存:子类构造器函数方法进栈
(6.堆内存:显示初始化父类的属性
(7.栈内存:父类构造方法进栈执行完毕出栈
(8.堆内存:显示初始化子类的属性
(9.栈内存:初始化完毕后,将栈内存中的地址赋值给引用变量,子类构造方法出栈

23.多态性
person 是stuent的父类;
person p = new student();
(1)方法的重载:本类中存在同名方法。
体现在相同名称可以实现不同逻辑
(2) 方法的重写:子类对父类方法的覆盖。
体现在子类可以使用和父类相同的方法名儿,覆盖父类的逻辑。(例如,父类的方法,想修改逻辑吗,但是有别的代码在调用父类的方法,可以考虑用子类继承父类,重新父类的方法;
(3) Java 引用变量有两个类型,编译时的类型和运行时的类型。
编译时类型由声明该变量时使用的类型决定person p
运行时类型由实际赋给该变量的对象决定;new student
(4)例如 person p = new person();
p = new student();

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210603204239951.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUxNDk3MDQx,size_16,color_FFFFFF,t_70)

运行时
在这里插入图片描述

->子类可看作是特殊的父类,所以父类类型的引用可以指向子类对象:向上转型
(5)属性
person p = new student ;
属性是在编译时确定的,编译时p为person类型,如果person里没有school属性,就会出错;而运行时不会出错
(6)虚拟方法调用:无论编译还是运行都能过
调用实际对象所属类中的重写方法;
(7)多态性小结
前提:——>需要存在继承或实现关系
——>要有覆盖操作
成员方法:
——>编译时:要查看引用变量所属的类中是否有所调用的方法
——>运行:调用实际对象所属的类中的重写方法
成员变量
——>不具备多态性,只看引用变量所属类;
(8)子类变量不会覆盖父类中的变量
(9)&_& 方法声明的形参类型为父类类型,可以使用子类的对象作为实参调用该方法:

public class Test{
	public void method(person e){
		//……
		e.getinfo();
	}
	public static void main (string args){
		Test t = new student();
		Student m = new Student();
		t.method(m);//子类的对象m传递给父类类型的参数e
	}
}

把子类看作是一个特殊的父类;

24.操作符instanceof
x instanceof A :检验x是否为类A的对象,返回值为boolean型
->要求x所属的类与类A必须是子类和父类的关系,否则编译错误。
->如果x属于类A的子类,x instanceof A值也为true
~if(e instanceof A)
//处理person类及其子类对象

~person e = new student();
System.out.println(e instanceof Student);
输出 true;
25.object 类
(1) 多层继承,处于最高级的父类一定是Object类
(2)Objict 类是所有java类的跟父类
(3)如果在类的声明中未使用extends关键字指明其父类,则默认为Object类
(4)例如:

public class Test {
	/**
	*问题,想给test设置一个形参参数,这个参数我不确定传									.	*进来一个什么类,可以确定的是传递实参一定是个类,那么test方法的形参需要设置什么类型呢?
	**/
	public void test(Object obj){
		
	}
	public static void main (string[] args){
		Test t = new Test();
		Person p = new Person();
		Student s = new Student();
		t.test(p);
		t.test(Object obj);//Object 传递类
		t.test(new Kk);//隐式对象(只用一次时)
		//public boolean equals(Object obj);
		//引用对象,判断是否是同一个对象
		System.out.println(p,equals(s));
		//输出 false
		//原因是p 和 s  不是同一个对象
		
		person e = new person();
		System.out.println(p,equals(e));
		//输出false
		//原因是e和p指向的是不同的类所以不是同一个对象
	
		k=p;
		System.out.println(p,equals(k));
		//输出true
		//原因是k和p指向了同一个对象;
		
		
	}
}

(5) object是所有类的父类,子类可以执行父类的方法。所以person的对象p可执行object的方法;

(6)public String toString()
打印对象内存地址
(7)用Object o = new person();
可以用Object接受子类的实例(new person 叫实例)

26.类型转换

(1)基本类型转换
(1.自动类型转换
小——>大
int i= 20;
long g = i;
double e = g;
(2.强制类型转换
大——>小
long l = 20L;
int i = (int) l;
(2)java对象强制类型转换——>造型
(1. 从子类到父类的类型可以自动进行

public class studet extends person{

}

public class test{
	public static void main(String[] args){
		student s  =  new student();
		person p = s ;//这里进行转换;
	}
	
}

(2. 从父类到子类的类型转换必须通过造型(强制转换)实现;

public class studet extends person{

}

public class test{
	public static void main(String[] args){
		person p = new person();
		student s = (student) p;//强制将父类person转换为student
	}
}

(3. 无继承关系的引用类型之间转换是非法的
(4.

//object 是所有类的最高父类;(无继承关系的 )

//子——>父
String s =" hello";
Object  obj = s;//从子类到父类类型转换自动进行
System.out.println(obj);
//输出hello

//父——>子
Object obj = "hello";
String s = (String) obj;//父——>子 强制转换
System.out.println(s);
//输出hello

(5.类型转换实例

public class test{
	public void method(person e){
	//判断main函数传过来的值是否是student类型
		if (e instanceof Student ){
		//类型的强制转换
			student me = (student) e;
			System.out.println(me.getschool());
		}
	}
	
	//main函数;
	public static void  main (String args[] ){
		test t = new test();
		strdent m = new student();
		t.method(m);//将student实例传入t.method的方法中
	}
}

(6.图例
在这里插入图片描述

  1. == 和 equals
    (1)
person p1 = new person();
person p2 = new person();
System.out.println(p1 == p2)
//返回false
person p3 = p1;
System.out.println(p1 == p3);
//返回true

==改为equals 等同;

(2)特例,当equals()方法进行比较时,对类file.String Date及包装类(Wrapper class )来说,是比较类型及内容儿不考虑引用的是否是同一个对象;(原因是 在这些类中重写了object类的equals()方法)

String s1 = new String(“abc”);
String s2 = new String(“abc”);
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
//输出true
//输出true

在这里插入图片描述

对于对象来说
特殊类,如String, file,date使用== 比较的是对象(对象的地址),equals比较的是内容;

除了特殊类之外的其他普通的类的对象,== 和 equals 比较的都是对象(对象的内存地址)

如果想改变某一个类的equals,不想用equals来比较对象的内存地址,就需要重写equals方法;

  1. String 对象的创建
    在这里插入图片描述

(1)字面量创建String对象
String s1 = “abc”;//常量池中添加“abc”对象,返回引用地址给s1对象,
String s2 = “abc”//通过equals方发判断产量池中已有值为abc的对象,直接返回相同引用;

(2)new创建String对象
String s3 = new String(“def”);//在常量池中添加“def”对象,在堆中创建为“def”的对象s3 ,返回指向堆中s3
的引用
String s4 = new String(“def”);//常量池中已有值为“def”,的 的对象,不做处理,在堆中创建值为def的对象s4,返回指向堆中s4的引用;

(3)String s5 = “X” + “Y”;//经过jvm优化,直接在常量池中添加xy对象;

(4)String s6 = new String(“1”) + new String(“2”);//通过StringBuilder实现,在常量中添加“1”和“2”两个对象,在堆中创建值为“112”的对象,把引用地址给s6;

  1. 包装类(Wrapper)
    在这里插入图片描述
    (1)->针对8种基本定义相应的引用类型——包装类
    ->有了类的特点,就可以调用类中的方法
    (2)装箱->拆箱
	//jdk 1.5之前
	 ->Integer i = new Integer(112);
	 -> int i0 = i.intValue();
	 //jdk 1.5之后自动拆装箱
	->Integer i1 = 112; 
	->int i2 = i1;

//boolean 类型的拆装箱
boolean b = new Boolean("false").booleanValue(); //jdk1.5 之前
boolean b = new Boolean("false");//自动拆箱
Boolean b1 = true;//自动装箱

(3)类型相互转换

//基本数据类型转String
int i = Integer.parseInt("123");
float f = Float.parseFloat("0.40");
boolean b = Boolean.parseBoolean("false");
//
String istr = String.valueOf(i);
String fstr = String.valueOf(f);
String bstr = String.Vlueof(true);

(4)toString
(1.输出当前对象的内存地址;源自于object的方法;

person p = new person();
System.out.println(m.toString)//与下同
System.out.println(p);
// 输出为p的内存地址
toString是

可以重写方法toString 去输出调用(有用)

  1. static——关键字(静态的)
    类变量->不用实例化就可以用(固定的,不随对象的变化而变化)
    实例变量->需要实例化 new后使用
public class chinese(){
//类变量不用实例化,直接类名.属性名就可以使用,是类的一部分,被所有的类的实例化对象所共享;(也叫静态变量)
	static String country;
	//实例变量,只有实例化后才能用,属于实例化对象的一部分,不能共用
	String name;
	int age;
}

主要用于类方法,类属性用的比较少;
主要用于写工具类;

//判断是不是字符串类方法
public class Utils{
	public Static boolean isEmpty(String s){//静态方法
		boolean flag = false;
		if(s != null && !s.equals("")){
			flag = true;
		}
		return flag;
	}	
	public Static void main(String[] args){
		String s= "";
		//这里不需要new对象(不需要实例化就可以调用,且所有类都可以)
		Syst.out.println(Utils.isEmpty(s));//判断s是字符串不
	}
}

使用范围
java类中,可用static修饰属性/方法/代码块/内部类/
被修饰后成员具备的特点
1)随着类的加载而加载(通过类名.属性或类名.方法)
2)优先于对象存在(不用new就可以用)
3)修饰的成员,被所有对象所调用()
4)访问权限允许时,可不创建对象,直接被类调用(权限是指public 等关键字)

public class chinese{
	public Chinese(){
		chinese.count += 1;
	}
	public static int count ;//计数
	public static void showCount(){
		System.out.println("总共new"+chinese.count+'个对象');
	}
	public static void main(String[] args){
		chinese c1 = new chinese();
		chinese c1 = new chinese();
		chinese c1 = new chinese();
		chinese c1 = new chinese();
		chinese c1 = new chinese();
		chinese.showCount(chinese.count);
	}
}
//输出new了6个对象;

类变量用起来要小心,因为一个变化就都变了
类方法:主要用于工具类
类方法里不能使用this和super(this/super 主要指的是对象)

31.单例设计模式——懒汉式/饿汉式
(1)设计模式:实际变成过程中逐渐总结出的一些解决问题的套路;
(2)new只用一次实例化,以后不论在哪都只调用这个实例(原因事new实例化对象需要消耗大量的时间和资源)
(3)饿汉式

public class Single {
	//构造器  这里的意思是私有化这个构造器然后用new不能实例化Single
	private Single(){//私有化
		
	}
	//私有的静态变量, 这里new实例化一次
	private static Single Sinle = new Single();
	//公有的静态方法,通过这个去使用Single类
	public static Single getInstance(){
		return single;
	}
}
//main函数里
//这里用的是类方法,去通过调用Single中的静态方法
Single s =  Single.getInstance();

懒汉式:

public class Single(){
//构造器私有化,外面不能直接对Single new实例化
	private Single(){
		
	}
	//第一次调用时,s1 为null 之后s1就是Single的对象;
	private staic Single s1 = null;
	public static Single getInstance(){
		if(s1 === null ){
			s1 = new Single();
		}
	}
}

(4)懒汉式和饿汉式的区别(什么时候new对象)

懒汉式:在第一次有人调用getlnstance方法时,来new对象,以后有人调用getlnstance方法直接返回之前第一次new好的对象;(暂时懒汉式还存在线程安全问题)

懒汉式:在类加载之后还没有调用的时候,就先new好一个对象,以后不论谁来调用getLnstance方法,都是直接返回之前new好的对象;

32.main方法
(1)由于java虚拟机需要调用类的main()方法,所以该方法的访问必须是public又因为java 虚拟机在执行main()方法时不必创建对象,所以该方法必须时static的,该方法接受一个String类型的数组参数,该数组中保存执行java命令时传递给所运行的参数;
(2)在这里插入图片描述
在这里插入图片描述
其中的abc 123 1kj sss是string[] argss字符串数组保存的传递给类的参数;
在这里插入图片描述
33.代码块-初始化块

public class Person{
	String name;
	public Person(){
		this.name = "张三";
		System.out.println("执行的是构造方法");
	
	//非静态的代码块
	{
		System.out.println("执行的非静态代码块");
	}
	static {
		System.out.println("执行的是静态代码块");
	}
	public static void main(String[] args){
		new person();
	}
	}
}

(2)执行顺序
在new person();执行的时候(多个态码块时,按顺序执行)
->类的属性的默认初始化,和显示初始化
->执行代码块的代码
->执行构造器的代码
(3)
静态代码块只能是执行静态修饰的成员;
静态代码只执行一次在多次new这个类时,
(4)静态代码块和非静态代码块区别

非静态代码块
->可以有输出语句
->库一堆类的属性声明进行初始化操作
->可以调用静态和非静态的变量和方法
->肉有多个非静态代码块按从上到下顺序执行
->每次创建都会执行一次,且先于构造器执行

静态代码块
->可以又输出语句
->可以对类的属性声明进行初始化操作
->不可以调用废静态的属性和方法
->若又多个静态代码块,那么按从上到下顺序执行
->静态代码块的执行要先于非静态代码块
->静态代码块只执行一次 

/
(5)用处
主要用途:静态代码块用来处理静态属性
->静态代码块,例子:

//对象类型属性
public class testperson{
	String name;
	int Age = 1;
}

public class person{
	String name;
	//类属性
	static testPerson tp = new testPerson();
	
//用静态代码块对静态类属性进行修改
static {
	tp.name = "";
	tp.age = 1;
}

->非静态代码块.例子

public class person{
	public void Test(){
		System.out.println("输出person的test");
	}
}
public class Test{
	public static void main(String[] args){
	
	//匿名内部类
	Person p = new Person(){
		//这里相当于构造了一个person的匿名子类
		//因为是匿名的类 所以没办法通过new的对象。去修改类,必须用到代码块
		{
			super.name = "李四";
		}
		
		//因为是子类所以可以使用方法重写 alt+/ 方法 调出person中的方法进行重写;
		@Override
		public void test(){
			public voidtest(){
				System。out.println("===");
			}
		}	
	}
	}	
}

34.final —— 关键字;
(1)final 关键字修饰,表示最终;
(2)final 修饰的类不能被继承,提高安全性和程序可读性
(3)final 标记的方法不能被类重写
(4)final 标记的变量(成员变量或局部变量)即称为常量,名称一般用大写,且只能被赋值一次。

  1. 抽象类 abstract class
    (1)
    -> 用abstract 关键字来修饰一个类时,这个类叫做抽象类
    -> 用abstract 来修饰一个方法时,该方法叫抽象方法
    (抽象方法:只有方法的声明,没有方法的实现,以分号结束:abstract int abstractMethod(int a);)
    -> 含有抽象方法的类必须被声明为抽象类
    -> 抽象类不能实例化,抽象类用来作为父类被继承的,抽象类的子类必须重写父类的抽象方法,并提拱方法体。若没有重写全部的抽象方法,仍为抽象类。
    -> 不能用abstract 修饰属性。私有方法,构造器,静态方法,fina的方法。
    -> 只有一个抽象方法,那么这个就必须时一个抽象类;
    (2)
public abstract class Animal {
//只要类中有一个抽象方法,就必须是抽象类
	public abstract void test();

	public ablic abstract void move();
}

class Dog extends Animal{
	@Override
	public void test(){
		
	}
	@Override
	public void move(){
		System.out.println("狗移动方式是跑")}
}

class Fish extends Animal{
	@Override
	public void test(){
		
	}
	
	@Override
	public void move(){
		System.out.println("鱼的方法是游");
	}
}
//抽象类可以做为子类,抽象类可以继承。
//这里的存在抽象方法所以必须用抽象类否则报错——此时报错;
class Bird extends Animal {
	@Override
	public void move(){
		
	}
	public abstract  void test();
}

//main
Dog.d = new Dog();
d.move();
//输出
狗的方式是跑

(3)
为什么抽象类不可以使用final关键字声明?
->抽象类不能被实例化,抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体;
->final是最终,他修饰的类最终类,不能被继承,抽象类,如果要使用,必须继承抽象类,实现那些抽象的方法;

一个抽象类中可以定义构造器吗?
->构造器可以有构造方法,只是不能直接重建抽象类的实例对象而已;抽象类不能实例化,new Vihicle()是非法的

  1. 模板方法实际模式
    (1)
    ->抽象类就像一个大纲,里面的抽象方法就是每个章节的标题
    ->子类根据这些标题把每个章节写出来
    (2)模板方法实际模式:
//这是一种思想;
//
abstract class Template{
//计算code()执行时间;
	public final void geTime(){
	//获取一个时间秒数
		long start = System.currentTimeMillis();
		//运行下面(也可以在上面)的重写后的抽象类code
		code();
		long end = Sysetm.currtentTimeMillis();
		System.out.println("执行时间是:"+(end - start));
	}
	public abstract void code();
}
class SubTemplate extends Template{
	//code方法的重写
	public void code(){
		for(int i=0;i<10000;i++){
			System.out.println(i);
		}
	}
}
// main
SubTemplate p = new SubTemplate();
p.code();

  1. 接口——理论
    (1)
    ~ 有时必须从几个类中派生出一个子类,继承他们所有的属性呵方法。但是java不支持多重继承。有了接口,就恶意得到多重继承的效果;
    ~ 接口(interface)是抽象方法和常量值的定义的集合;
    ~ 从本质上讲,接口是一种特殊的抽象类,这种抽象类只包含常量和方法的定义,而没有变量和方法的实现
    ~ 实现接口类:
    class SubClass implements InterfaceA{}
    ~ 一个类可以实现多个接口,接口也可以继承其他接口
    (2)
    接口特点:
    ~ 用interface来定义
    ~ 接口的所有成员变量都是由public static final 修饰的
    ~ 接口中的所有方法都默认是由public abstract 修饰的
    ~ 接口没有构造器
    ~ 接口采用多层继承机制

    	举例:
    
public interface Runner{
int ID = 1;//相当于public static final int ID = 1;
void start();//相当于public abstact void start();
public void run();
void stop();
}
(3)接口举例;
//接口;
public interface TestIn{
int ID = 1;
void test();
}

public interface TestIn1{
int ID = 1;
void test1();
}
//类可以实现多个接口,多个接口之间用,分隔
public class TestInImpl implements TestIn,TestIn1{
	@Oyerride
	public void test(){
	}

	@Override
	public void test1(){
	}
}
//接口可以**继承**接口
public interface TestIn2 exends TesInl{

}

(4)
~实现接口的类中必须提供接口中所有的方法的具体实现内容,方可实例化,否则仍为抽象类;

//此时会报错,因为类没有实现接口的所有方法,这个类就需要定义为抽象类;
//public 后加abstract

public class TestInImpl1 implements TestIn{

}
~ 接口类主要功能就是被实现类实现。(面向接口编程)
与继承关系类似,接口与实现类之间存在多态性
定义java类中的语法格式:先写extends,后写implements
//如果一个类既继承父类,又实现接口
//那么先继承,再实现
public class TestInImpl2 extends Person implements TestIn,TestIn1{
	@Override
	public vod test(){

	}
	@Override
	public void test1(){

	}
}

(5)
在这里插入图片描述
如果抽象类父类需要改变,不能修改,父类修改后子类也会跟着变化,这里就需要接口了,把子类需要的抽象方法,写入接口然后实现(接口的的调用叫实现),接口也可以继承;

  1. 接口举例
    (1)
    在这里插入图片描述
    在这里插入图片描述
//抽象类
public astract class Person1{
	int age  ;
	String name ;
	int sex;
	public abstract void showInfo();
}

pubic interface Cooking {
	void fry();//炒菜
}

public interface Sing{
	void singing();//唱
}

public class SCTeacher extends PErson1 inplements Cooking ,Sing {
	String course;//教的科目
	
	public void setInfo(){
		super.age = 27;
		super.name = "王富贵";
		super.sex = 1;
		
		this .course = "数学";
	}
	
	@Override
	public void showInfo(){
		System.out.println("会唱歌的厨子的老师是信息");
		System.out.println(super.age);
		System.out.println(super.name);
		System.out.println(super.sex);
		System.out.println(this.course);
	}
	
	@Override
	public void fry(){
		System.out.println(super.name + "老师拿手的厨艺是炒菜");
	}

	@Override
	public void singing(){
		System.out.println(super.name + "老师善长美声唱法");
	}
}

//main
SCTeacher sct = new SCTeacher();
sct.setInfo();
sct.showInfo();
sct.fry();
sct.singing();
//可以用接口来接受new
/**
*cooking c = new SCTeacher();//体现对象多态
*c.fry();//此时没有其他的什么方法;
*
**/

(2)如果类没有实现接口的所有方法,那么这个类就是抽象类;

  1. 工厂模式——写代码的一种方式
    (1)需要解决的问题;在这里插入图片描述
    (2)
//创建接口
public interface BWM{
	void showInfo();
}
//以下调用接口
class BWM3 implements BWM{
	@Override
	public void  showInfo(){
		System.out.println("这是宝马3系")}
}

class BWM5 implements BWM{
	@Override
	public void  showInfo(){
		System.out.println("这是宝马5系")}
}

class BWM7 implements BWM{
	@Override
	public void  showInfo(){
		System.out.println("这是宝马7系")}
}

///创建接口,返回BWM接口(因为以上都是用的BWM接口)
public interface BWMFactory{
	BWM productBWM();//这里的BWM确定的是方法的返回值是BWM类型的
}

class BWM3Factory implememnts BWMFactory{

	@Override
	public BWM productBWM() {//被主函数调用
		System.out.println("生产宝马3系车")return new BWM3//返回BWM3的类
		
	}
}

class BWM5Factory implememnts BWMFactory{

	@Override
	public BWM productBWM() {//被主函数调用
		System.out.println("生产宝马5系车")return new BWM5//返回BWM5的类
		
	}
}

class BWM7Factory implememnts BWMFactory{

	@Override
	public BWM productBWM() {//被主函数调用
		System.out.println("生产宝马7系车")return new BWM7//返回BWM7的类
		
	}
}
//main 方法
public class Test2{
	public static void main(String{} args){
		BWM b3 = new BWM3Factory().productBWM();
		b3.showInfo();
		
		BWM b5 = new BWM5Factory().productBWM();
		b5.showInfo();
		
		BWM b7 = new BWM7Factory().productBWM();
		b7.showInfo();
	}
}

(3)通过工厂把new对象给隔离,通过产品的接口可以接受不同的实际产品实现类,实例的类名的改变不影响其他合作开发成员的编程;(类名都不受影响,其他的更不受影响)

  1. 内部类
    (1)
    ~ 在java 中,允许一个类的定义位于另一个类的内部,前面称内部类,后者称外部类
    ~ inner class 一般用在定义它的类或语句块之内,在外部引用他时必须给出完整的名称,inner class 的名字不能与包含他的类名相同;
    ~inner class 可以使用外部类的私有数据,因为它时外部类成员,同一个类的成员之间可相互访问。
    ~ 分类:成员类(static 成员内部类和非static成员内部类)
    局部内部类(不谈修饰符/)匿名内部类
    (2)
public class Test3{
	int i;
	public int z;
	private int k;
	class A{
		int i;
		public void setTest3Fileds(){
			Test3.this.i = 1;//区分内部类中的i和外部类中的i
			Test3.this.z = 1;
			Test3.this.k = 1;
		}
		public void set(){
			this.i = 10;
		} 
	}
	public void setInfo(){
		new A().setTest3Fileds();
	}
	public void showInfo(){
		System.out.println(this.i);
		System.out.println(this.z);
		System.out.println(this.k);
	}
}
(3) Inner class 作为类的成员:
	~ 可以声明为final的(最终类)
	~和外部类不同,Inner class可声明为private或protected
	~ Inner class可以声明为static的,但此时就不能使用外层类的非static的成员变量;
	~ Inner class 作为类:
	~可以声明为abstract 类,因此可以被其它内部类或static的内部类中才可声明static成员。

(4)内部类解决的问题是:多重继承(接口也可以)
(5)

public class Test4{
	public static void main(String [] args){
		A a = new A();
		a.testB();
		a.testC();
	}
}
//使类A同时获得BC两个类的方法,并重写;
class A{
	public void testB(){
		new InnerB().tesB();
	}
	public void testC(){
		new InnerC().testC();
	}
	private class InnerB extends B{
		@Override
		public void testB(){
			System.out.println("这是重写之后的testB方法")
		}
	}
	private class InnerC extends C{
		@Override
		public void test(){
			System.out.println("这是重写之后testC的方法")
		}
	}
}

class B{
	public void testB(){
	}
}

class C{
	public void testC(){
	}
}
  1. 面向对象的总结
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值