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>0)
age=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.图例
- == 和 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方法;
- 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;
- 包装类(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 去输出调用(有用)
- 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 标记的变量(成员变量或局部变量)即称为常量,名称一般用大写,且只能被赋值一次。
- 抽象类 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)
->抽象类就像一个大纲,里面的抽象方法就是每个章节的标题
->子类根据这些标题把每个章节写出来
(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)
~ 有时必须从几个类中派生出一个子类,继承他们所有的属性呵方法。但是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)
//抽象类
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)需要解决的问题;
(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)
~ 在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(){
}
}
- 面向对象的总结