1、面向对象概念
面向对象是一种思想,可以让复杂的问题简单化,可以让程序员的角色从执行者转变为指挥者。
***可以想几个面向对象在生活中的例子(面试经常会问到面向对象的思想?)
面向过程强调的是功能行为,而面向对象是将功能封装进对象,强调的是具备了功能的对象。
2、面向对象特征:封装,继承,多态。
开发:找对象,建立对象,使用对象。维护对象的关系。
3、类和对象的关系
类:就是对现实生活中事物的描述,是对具体事物的抽象。即提取对象中的共性内容。映射到java中就是class定义的类。
对象:就是这类事物实实在在存在的个体。映射到java中就是用new建立的实体。
生活中描述事物无非就是描述事物的属性和行为。如:人有身高、体重等属性,有说话、学习等行为。
属性:对应类中的变量。
行为:对应类中的函数(方法)。
定义类:就是在描述事物, 就是在定义属性和行为。属性和行为共同成为类中的成员(即成员变量和成员函数)。
4、成员变量和局部变量的区别
作用范围
成员变量:作用于整个类中
局部变量:作用于函数中,或者语句中。
存储位置
成员变量:存在于堆内存中,因为对象的存在,才在内存中存在。
局部变量:存在栈内存中。
例:
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:Microsoft YaHei;font-size:14px;">class Car
{
//描述颜色
String color = "red";
//描述轮胎数
int num = 4;
//运行行为
void run()
{
System.out.println(color+"..."+num);
}
}
class CarDemo
{
public static void main(String[] args)
{
//生产汽车。在java中通过new操作符来完成。
//其实就是在堆内存产生一个实体。
Car c = new Car();//c就是一个类类型变量。记住:类类型变量指向对象。
//需求:将已有车的颜色改成蓝色。指挥该对象做事情。在java中指挥方式是:对象.对象成员
c.color = "blue";
c.run();
Car c1 = new Car();
c1.run();
}
}</span></span>
运行结果:
5、对象在内存中的存储:
栈内存:用于存储局部变量,当数据使用完,所占空间会自动释放。局部变量没有默认初始化值,不初始化是不可以参与运算的。
堆内存:用于存储通过new建立的实体(数组和对象),每一个实体都有内存地址值,且实体中的变量都有默认初始化值,当实体不再被使用,虚拟机会在不确定的时间回收垃圾。
栈内存 堆内存
6、匿名对象
格式:new Xxx().xxx;
匿名对象使用方式一:当对象的方法只调用一次时,可以用匿名对象来完成。这样写比较简化。
例:
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:Microsoft YaHei;font-size:14px;">class CarDemo
{
public static void main(String[] args)
{
new Car().num = 5;
new Car().color = "blue";
new Car().run();
}
}</span></span>
匿名对象在内存中的存储:
***当没有变量指向对象时,堆内存中的对象就会变成垃圾,由虚拟机不定时回收,若想对象变垃圾可以自己指定:x=null;
匿名对象使用方式二:可以将匿名对象作为实际参数进行传递。
例:
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:Microsoft YaHei;font-size:14px;">class CarDemo
{
public static void main(String[] args)
{
Car q = new Car(); //可以直接将匿名对象作为实际参数进行传递
show(q); // show(new Car());
}
public static void show(Car c)
{
c.num = 3;
c.color = "black";
c.run();
}
}</span></span>
7、封装概述
封装:指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
封装原则:把属性都隐藏,提供公共方法对其访问。对私有变量一般都提供setxxx及getxxx两个函数。
java中函数是最小的封装体,类,包,框架。
private 关键字
private:私有,权限修饰符:用于修饰类中的成员(成员变量,成员函数)。私有只在本类中有效。
注意:私有仅仅是封装的一种表现形式。
之所以对外提供访问方式,就因为可以在访问方式加入逻辑判断等语句,对访问数据进行操作,提高代码健壮性。
例:
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:Microsoft YaHei;font-size:14px;">class Person
{
private int age;
public void setAge(int a)
{
if (a>0 && a<130)
{
age =a;
}
else
System.out.println("illegal age");
}
public int getAge()
{
return age;
}
void speak()
{
System.out.println("age:"+age);
}
}
class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
System.out.println(p.getAge());
p.setAge(20);
System.out.println(p.getAge());
p.speak();
}
}</span></span>
8、构造函数:与类名同名,无返回值类型,无return语句。
构造函数的作用:可以用于给对象初始化。
对象一建立就会调用与之对应的构造函数。构造函数可以重载,用于给对应的对象进行初始化。
当一个类中没有定义构造函数时,那么系统会默认给该类加一个空参数的构造函数。如果在类中定义了指定的构造函数,那么类中的默认构造函数就没有了。
构造函数与一般函数的区别:
构造函数:对象一建立就运行。给对象初始化。一个对象建立,构造函数只运行一次。
一般函数:对象调用时才执行。给对象添加对象具备的功能。一般函数可以被对象调用多次。
9、构造代码块:定义的是不同对象共性的初始化内容。给所有对象进行统一初始化。对象一建立就执行,且优于构造函数执行。
***开发一般不用,面试可能会问到构造函数执行顺序。
例:
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:Microsoft YaHei;font-size:14px;">class Person
{
private String name;
private int age;
public void setName(String n)
{
name = n;
}
public String getName()
{
return name;
}
public void setAge(int a)
{
if (a>0 && a<130)
{
age =a;
}
else
System.out.println("illegal age");
}
public int getAge()
{
return age;
}
{
cry();//构造代码块
}
Person()
{
System.out.println("A:name="+name+"---age="+age);
}
Person(String n)
{
name = n;
System.out.println("A:name="+name+"---age="+age);
}
Person(String n ,int a)
{
name = n;
age = a;
System.out.println("A:name="+name+"---age="+age);
}
public void cry()
{
System.out.println("cty.....");
}
}
class PersonDemo2
{
public static void main(String[] args)
{
Person p = new Person();
p.setName("mss");
p.setAge(13);
System.out.println("name="+p.getName()+";age="+p.getAge());
Person p1 = new Person("mashasha");
p1.setName("mashashagai");
p1.setAge(23);
System.out.println("name="+p1.getName()+";age="+p1.getAge());
Person p2 = new Person("mashasha",22);
}
}</span></span>
运行结果:
10、this关键字
this:代表它所在函数所属对象的引用。简单说:哪个对象在调用this所在的函数,this就代表哪个对象。
类中的变量及函数其实都省略了this.
this的应用:
(1)用于区分局部变量和成员变量同名的情况。
(2)当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。(但凡本类功能内部使用到了本类对象,都用this表示).
(3)用于构造函数之间进行相互调用。注意:
this语句只能定义在构造函数的第一行。因为初始化要先执行。
例:
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:Microsoft YaHei;font-size:14px;">class Person
{
private String name;
private int age;
Person(String name)
{
this.name = name;//出现同名变量,将成员变量省略的this.显示的写出来。
}
Person(String name ,int age)
{
this();//用于构造函数之间进行相互调用
this.age = age;
}
public void speak()
{
System.out.println("My name is "+name+" . I am "+age+" years old .");
//成员变量省略了this.
//也可以写成System.out.println("My name is "+this.name+" . I am "+this.age+" years old .");
show();
//成员函数省略了this.
//也可以写成this.show();
}
public void show()
{
System.out.println("name="+name+"---age="+age);
}
/*
需求:给人定义一个功能用于比较年龄是否相同,也就是是否为同龄人。
*/
public boolean compare(Person p)
{
return this.age==p.age;//本类功能使用本类对象
}
}
class PersonDemo3
{
public static void main(String[] args)
{
Person p = new Person("mss",20);
Person p1 = new Person("mashasha",20);
p.speak();
p1.speak();
boolean b = p.compare(p1);
System.out.println(b);
}
}</span></span>
运行结果:
11、static关键字
用法:是一个修饰符,用于修饰成员(成员变量,成员函数)。
当成员被static修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用。类名.静态成员。
特点:
(1)随着类的加载而加载。也就是说:静态会随着类的消失而消失。说明它的生命周期最长。
(2)优先于对象存在。
(3)被所有对象所共享。
(4)可以直接被类名所调用。
实例变量和类变量的区别
存放位置
类变量随着类的加载而存在于方法区中。
实例变量随着对象的建立而存在于堆内存中。
生命周期
类变量生命周期最长,随着类的消失而消失。
实例变量生命周期随着对象的消失而消失。
静态的使用注意事项:
(1)静态方法只能访问静态成员(静态成员变量和静态成员函数)
非静态方法即可以访问静态也可以访问非静态。
(2)静态方法中不可以定义this,super关键字。
因为静态优先于对象存在。
(3)主函数是静态的。
静态有利有弊
利处:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。
可以直接被类名调用。
弊端:生命周期过长。
访问出现局限性。(静态只能访问静态)
什么时候使用静态?
要从两方面下手:
因为静态修饰的内容有成员变量和成员函数。
什么时候定义静态变量(类变量)呢?
当对象中出现共享数据时,该数据被静态所修饰。
例:定义一个Person类,成员变量包括姓名和国籍,国籍都为中国,就可以将国籍静态。
对象中的特有数据要定义成非静态存在于堆内存中。
什么时候定义静态函数呢?
当功能内部没有访问到非静态数据(对象特有的数据),那么该功能可以定义成静态的。
例:工具类
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:Microsoft YaHei;font-size:14px;">//java的说明书通过文档注释来完成。
/**
这是一个可以对数组进行操作的工具类,该类中提供了,获取最值,排序等功能。
@author mashasha
@version V1.1
*/
class ArrayTool
{
private ArrayTool(){}//构造函数私有化,强制该类不能建立对象,防止内存中产生一些没有用的对象。
/**
获取一个整形数组中的最大值。
@param arr 接受一个int类型的数组。
@return 会返回一个该数组中的最大值。
*/
public static int getMax(int[] arr)
{
int max = 0;
for (int i=1; i<arr.length; i++ )
{
if(arr[i]>arr[max])
max = i;
}
return arr[max];
}
/**
获取一个整形数组中的最小值。
@param arr 接受一个int类型的数组。
@return 会返回一个该数组中的最小值。
*/
public static int getMin(int[] arr)
{
int min = 0;
for (int i=1; i<arr.length; i++ )
{
if(arr[i]<arr[min])
min = i;
}
return arr[min];
}
/**
给int数组进行选择排序。
@param arr 接受一个int类型的数组。
*/
public static void selectSort(int[] arr)
{
for (int x=0;x<arr.length-1;x++)
{
for (int y=x+1;y<arr.length;y++)
{
if (arr[x]>arr[y])
{
swap(arr,x,y);
}
}
}
}
/**
给int数组进行冒泡排序。
@param arr 接受一个int类型的数组。
*/
public static void bubbleSort(int[] arr)
{
for (int x=0;x<arr.length-1;x++)
{
for (int y=0;y<arr.length-x-1;y++)
{
if (arr[y]>arr[y+1])
{
swap(arr,y,y+1);
}
}
}
}
/**
给int数组中的元素进行位置置换。
@param arr 接受一个int类型的数组。
@param a 要置换的位置。
@param b 要置换的位置。
*/
private static void swap(int[] arr,int a,int b)//不需要提供给用户,将其私有化。
{
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
/**
用于打印数组中的元素。
@param arr 接受一个int类型的数组。
*/
public static void printArray(int[] arr)
{
System.out.print("{");
for (int x=0;x<arr.length;x++)
{
if (x!=arr.length-1)
{
System.out.print(arr[x]+",");
}
else
System.out.println(arr[x]+"}");
}
}
}
public class ArrayToolDemo
{
public static void main(String[] args)
{
int[] arr = {3,4,8,43,22,77,23,576};
//ArrayTool tool = new ArrayTool();
int max = ArrayTool.getMax(arr);
System.out.println("max="+max);
int min = ArrayTool.getMin(arr);
System.out.println("min="+min);
ArrayTool.printArray(arr);
ArrayTool.selectSort(arr);
ArrayTool.printArray(arr);
}</span></span>
运行结果:
帮助文档的制作。用帮助文档注释,用javadoc.exe提取即可。javadoc.exe只能提取public修饰的类。
运行结果:
12、静态代码块
格式:
static
{
静态代码块中执行的语句。
}
特点:随着类的加载而执行,只执行一次。
作用:用于给类进行初始化。
***要知道执行顺序。考试会考。
例:
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:Microsoft YaHei;font-size:14px;">class StaticCode
{
StaticCode()
{
System.out.println("a");
}
//静态代码块,给类进行初始化。
static
{
System.out.println("b");
}
//构造代码块,给对象进行初始化。
{
System.out.println("c");
}
//构造函数,给对应对象进行初始化。
StaticCode(int x)
{
System.out.println("d");
}
}
class StaticCodeDemo
{
public static void main(String[] args)
{
new StaticCode(4);
}
}</span></span>
打印结果为bcd.
13、对象初始化的过程。
例:Person p = new Person("mashasha",20);
该句话都做了什么事?
1、因为new用到了Person.class,所以会先找到Person.class文件并加载到内存中。
2、执行该类中的static代码块,如果有的话,给Person.class类进行初始化。
3、在堆内存中开辟空间,分配内存地址。
4、在堆内存中建立对象的特有属性。并进行默认初始化。
5、对属性进行显示初始化。
6、对对象进行构造代码块初始化。
7、对对象进行对应的构造函数初始化。
8、将内存地址赋给栈内存中的P变量。
14、设计模式:解决某一类问题最行之有效的方法。
java中有23种设计模式。
单例设计模式:解决一个类在内存中只存在一个对象。
例:程序A、B都要用到同一个配置文件。这个配置文件就是这个类中存在的唯一一个对象。
分析:想要保证对象唯一。
1、为了避免其他程序过多建立该类对象。先禁止其他程序建立该类对象。
2、为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。
3、为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。
方法:
1、将构造函数私有化。
2、在本类中创建一个本类对象。
3、提供一个方法可以获取到该对象。
方法一:
饿汉式:先初始化对象。single类一进内存,就已经创建好了对象。
例:
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:Microsoft YaHei;font-size:14px;">class Single
{
private Single(){} //将构造函数私有化。
private static Single s = new Single(); //在本类中创建一个本类对象。
public static Single getInstance() //提供一个方法可以获取到该对象。
{
return s;
}
}</span></span>
方法二:
懒汉式:对象在方法被调用时才初始化,对象延时加载。Single类进内存,对象还未存在,只有调用getInstance方法时,才建立对象。
例:
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:Microsoft YaHei;font-size:14px;">class Single
{
private Single(){} //将构造函数私有化。
private static Single s = null; //在本类中创建一个本类对象。
public static Single getInstance() //提供一个方法可以获取到该对象。
{
if(s==null)
s = new Single(); //对象延时加载。
return s;
}
}</span></span>