1.Java面向对象学习的三条主线
- Java类及类的成员:属性、方法、构造器:代码块、内部类
- 面向对象三大特征:封装、继承、多态
- 其他关键字:this、super、static、final、abstract、interface、package、import
2.面向对象与面向过程(人把大象装进冰箱)
2.1面向过程
强调功能行为,以函数为最小单位,考虑怎么做。
1.把冰箱门打开
2.抬起大象,塞进冰箱
3.把冰箱门关闭
2.2面向对象
强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
人{
打开(冰箱){
冰箱.开开();
}
抬起(大象){
大象.进入(冰箱);
}
关闭(冰箱){
冰箱.闭合();
}
}
冰箱{
开开(){}
闭合(){}
}
大象{
进入(冰箱){}
}
3.面向对象的两个要素:类和对象
class Person{
String name;
int age;
boolean isMale;
public void eat(){
System.out.println("人可以吃饭");
}
}
public class PersonTest{
public static void main(String[] args){
Person p1 = new Person();
Scaner scanner = new Scanner(System.in);
p1.name = "Tom";
p1.eat();
}
}
3.1类
对一类事物的描述,是抽象的、概念上的定义 类的结构:属性、方法
3.1.1属性
对应类中的成员变量,有默认初始化值
属性 vs 局部变量
不同点: 1.在类中声明的位置不同 属性:直接定义在类的一对{}中。 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量。 2.关于权限修饰符(private,public,缺省,protected)的不同 属性:可以在声明属性时,指明其权限(使用权限修饰符)。 局部变量:不可以使用权限修饰符。 3.默认初始化值的情况 属性:类的属性,根据其类型都有默认初始化值 整型(byte,short,int,long):0 浮点型(float,double):0.0 字符型(char):0或 ‘\u0000’ 布尔型(boolean):false 引用数据类型(类、数组、接口):null 局部变量:没有默认初始化值。意味着在调用局部变量前要赋初值。 4.在内存中加载的位置 属性(非static):加载到堆空间 局部变量:加载到栈空间
3.1.2方法
对应类中的成员方法 声明: 权限修饰符 返回值类型 方法名(形参列表){ 方法体 }
3.2对象
是实际存在的该类事物的每个个体,因而也称为实例
“万事万物皆对象” 1.在java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构。 2.涉及到java语言与前端html、后端数据库交互时,前后端的结构在java层面交互时,都体现类、对象。
对象数组
创建一个Student类,包括学号num(int)、年级state(int)、成绩score(int). 创建20个学生对象,学号为1-20,年级和成绩由随机数确定。 问题一:打印3年级学生信息 问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
提示: 1.生成随机数:Math.random(),返回值类型为double 2.四舍五入取整:Math.round(double d),返回值类型long
public class demo1 {
public static void main(String[] args) {
Student[] st=new Student[20];
for(int i=0;i<20;i++) {
st[i] = new Student();
st[i].num = i + 1;
st[i].state = (int) (Math.random() * 6 + 1);
st[i].score = (int) (Math.random() * 100);
}
demo1 d=new demo1();
d.search(st,3);
d.sort(st);
}
public void search(Student st[],int sta){
for(int i=0;i<st.length;i++){
if (st[i].state == sta) System.out.println(st[i].Info());
}
}
public void sort(Student st[]){
for(int i=0;i<st.length-1;i++){
for(int j=0;j<st.length-1-i;j++){
if(st[j].score>st[j+1].score){
Student temp=st[j];
st[j]=st[j+1];
st[j+1]=temp;
}
}
}
print(st);
}
public void print(Student st[]){
for(int i=0;i<st.length;i++){
System.out.println(st[i].Info());
}
}
}
class Student{
int num;
int state;
int score;
String Info(){
return ("学号:"+num+" 年级:"+state+" 成绩:"+score);
}
}
匿名对象
在上面代码的基础上
new Student().num=10;
new Student().Info();
理解:创建的对象没有显式的赋给一个变量名,即为匿名对象。 特点:匿名对象只能调用一次。每次new一个对象都是新的对象。 使用:往往在方法调用使用,作为参数传进去。
3.3内存解析
 对象的内存解析:  引用类型的变量,只可能存储两类值:null和地址值。
4.方法
4.1方法的重载(overload)
概念:在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同即可。 与权限修饰符、返回值类型、形参变量名无关。 System.out.println()就是一个典型的重载方法。
4.2可变个数的形参
是jdk5.0新增内容
public class demo2 {
public static void main(String[] args) {
demo2 d=new demo2();
d.show(1);
d.show("h");
d.show("h1","h2");
d.show();
d.show(new String[]{"aa","bb","cc"});
}
public void show(int i){}
public void show(String s){}
public void show(String ...str){
for(int i=0;i<str.length;i++){
System.out.println(str[i]);
}
}
public void show(String[] str){}
}
可变个数的形参格式:数据类型…变量名 形参个数可以为0到任意个。 可变个数的形参方法,与本类方法中方法名相同、形参不同的方法,构成函数重载。 可变个数形参在方法的形参中只能声明在末尾:
public void show(int i,String...str){}
应用:在数据库查询时可能用到。
4.3值传递机制
4.3.1关于变量的赋值
1.变量是基本数据类型 此时赋值的是变量所保存的数据值。
int m=1;
int n=m;
n=2;
2.变量是引用数据类型 此时赋值的是变量所保存的地址值。
Order o1=new Order();
o1.num=1001;
Order o2=o1;
o2=1002;
4.3.2方法形参的值传递机制
1.形参是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
public class demo3 {
public static void main(String[] args) {
int m=10;
int n=20;
demo3 d=new demo3();
d.swap(m,n);
System.out.println("m="+m+" n="+n);
}
public void swap(int m,int n){
int swap=m;
m=n;
n=swap;
}
}
内存解析:  swap()调用结束后,栈中swap()的局部变量释放(出栈),在main()中输出的m,n仍是栈中的m,n的值。 2.参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。  左边为栈,右边为堆。 栈底data为main()中的data. swap()调用结束后,栈顶temp和data出栈,栈中只剩下main()中的data,此时data指向堆中已经修改后的对象。因此成功交换m,n
4.4递归方法
一个方法体内调用它的自身。 例1:已知有一个数列,f(0)=1,f(1)=4,f(n+2)=2*f(n+1)+f(n),其中n是大于0的整数,求f(10)的值。
public class demo4 {
public static void main(String[] args) {
demo4 d=new demo4();
System.out.println(d.digui(10));
}
public int digui(int n){
if(n==0)return 1;
else if(n==1)return 4;
else{
return 2*digui(n-1)+digui(n-2);
}
}
}
例2:输出斐波那契数列第n个数
public class demo5 {
public static void main(String[] args) {
demo5 d=new demo5();
System.out.println(d.digui(10));
}
public int digui(int n){
if(n==1||n==2)return 1;
else{
return digui(n-1)+digui(n-2);
}
}
}
5.封装性(封装和隐藏)
程序设计追求“高内聚,低耦合”。 高内聚:类的内部数据操作细节自己完成,不允许外部干涉。 低耦合:仅对外暴露少量的方法用于使用。
隐藏对象内部的复杂性,只对外公开简单的接口()。便于外界调用,从而提高系统的可扩展性、可维护性。
5.1问题的引入
当我们创建一个类的对象以后,我们可以通过“对象.属性”的方式对属性进行赋值。这里,赋值操作要受到属性的数据结构和存储范围的制约。除此之外,没有其他制约条件。 但是,在实际问题中,我们往往需要给属性的赋值加入额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。 限制了用户再使用“对象.属性”的方式。
5.2封装性的体现
1.将类的属性(xxx)私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值。
public class AnimalTest {
public static void main(String[] args) {
Animal an=new Animal();
an.name="小狗";
an.age=1;
an.setLegs(4);
an.getLegs();
an.print();
}
}
class Animal{
String name;
int age;
private int legs;
public void setLegs(int l){
if(l>=0&&l%2==0) legs=l;
else legs=0;
}
public int getLegs(){
return legs;
}
public void print(){
System.out.println("name:"+name+" age:"+age+" legs:"+legs);
}
}
2.将类的方法私有化,仅供类内使用 3.单例模式 ……
5.3四种权限修饰符
权限从小到大:private、缺省、protected、public
修饰符 | 类内部 | 同一个包 | 不同包的子类 | 同一个工程 |
---|
private | yes | | | | 缺省 | yes | yes | | | protected | yes | yes | yes | | public | yes | yes | yes | yes |
四种权限可以修饰类,和类的内部结构:属性、方法、构造器、内部类。 只能使用缺省和public修饰类,但是四种权限都可以修饰类的内部结构(属性、方法、构造器、内部类)。
为什么不能用protected修饰类? 因为如果类能被protected修饰,那么这个类就一定是子类,也就是内部类,内部类可以被四种权限修饰符修饰。但是原本的问题中这个类并不是内部类。
6.构造器(构造方法)
定义构造器的格式:权限修饰符 类名(形参列表){} 一个类中的多个构造器,彼此构成重载。
注意: 如果没有显式的定义类的构造器,则系统默认提供一个空参的构造器,此默认构造器的权限和该类的权限相同。 一旦显式的定义了类的构造器,系统就不再提供默认的空参构造器。 一个类中至少存在一个构造器,可以是默认的,也可以是自己定义的。
6.1构造器的作用:
1.创建对象
public class PersonTest {
public static void main(String[] args) {
Person p=new Person();
p.setAge(12);
}
}
public class Person {
private int age;
public void setAge(int a){
age=a;
}
public int getAge(){
return age;
}
}
2.初始化对象的信息
public class PersonTest {
public static void main(String[] args) {
Person p=new Person("Tom");
}
}
public class Person {
private int age;
String name;
public Person(){
System.out.println("Person()");
}
public Person(String n){
name=n;
}
}
6.2总结属性赋值的先后顺序
1.默认初始化值 2.显式初始化 3.构造器赋值 4.通过“对象.方法”或“对象.属性”的方式赋值
以上操作执行的先后顺序:1 -> 2 -> 3 -> 4
7.JavaBean
JavaBean是一种java语言写成的可重用组件
JavaBean是符合以下标准的java类: 1.类是公共的 2.有一个无参的公共构造器 3.有属性,且有对应的get、set方法
……待更
8.UML类图

9.this关键字
public class Person {
private int age;
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
public Person(int age){
this.age=age;
}
public void eat(){
System.out.println("eat");
this.sleep();
}
public void sleep(){
System.out.println("sleep");
}
}
this关键字的使用: 1.this可以修饰属性、方法、构造器。 2.this可理解为当前的对象或当前正在创建的对象。 3.在类的方法中,可以使用"this.属性"或"this.方法"的方式,调用当前对象的属性或方法。 但是,通常情况下我们都选择省略"this." 特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。 4.在类的构造器中,可以使用"this.属性"或"this.方法"的方式,调用当前正在创建的对象的属性或方法。 但是,通常情况下我们都选择省略"this." 特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。 5.this调用构造器 在类的构造器中,可以显式的使用this(形参列表)方式,调用类中指定的其他构造器。 构造器中不能通过this(形参列表)方式调用自己 如果一个类中共有N个构造器,那么最多有N-1个构造器中使用this(形参列表) 规定:this(形参列表)必须声明在当前构造器的首行。
public class Person {
private int age;
String name;
public Person(){
age=18;
}
public Person(int age){
this();
this.age=age;
}
public Person(String name,int age){
this(age);
this.name=name;
}
}
10.package关键字
package cn.demo.day.day02;
为了更好的实现项目中类的管理,提供了包的概念。 使用package声明类或者接口所属的包,声明在源文件的首行。 包属于标识符,需要遵循标识符命名的规范。 每 “.” 一次,就代表一层文件目录。
补充:同一个包下,不可以命名同名的接口、类。
11.import关键字
作用:在源文件中显式的使用import结构导入指定包下的类、接口 声明在包的声明和类的声明之间。 如果需要导入多个结构,则并列写出即可。
import xxx.*;
import java.lang;
如果使用的类或接口是本包下定义的,则可以省略import结构。 如果在源文件中,使用了不同包下的同名的类,则必须至少有一个类需要以全类名的方式显示。 如果使用“xxx.*”方式表明可以调用xxx包下的所有结构。但是若使用xxx子包下的结构,则只能显式的导入。
import static表示导入指定类或接口中的静态结构(属性或方法)。 如:
import static java.long.System.* ;
import static java.long.Math.*;
out.println("hi");
long num=round(123.123);
12.MVC设计模式

|