面向过程(Procedure Oriented)和面向对象(Object Oriented,OO)都是对软件分析、设计和开发的一种思想,它指导着人们以不同的方式去分析、设计和开发软件。
面向对象编程,是一种通过对象的方式,把现实世界映射到计算机模型的一种编程方法。
一、类与对象
类(Class):是对一类事物的描述 ,是抽象的 、概念上的定义。由属性(Field)、方法(Method)和构造方法(Constructor )组成。
对象(Object):是实际存在的该类事物的每个个体,因而也称为实例(instance)。
如:“书”是一种抽象的概念,所以它是类,而《Java核心技术》、《Java编程思想》是对象。
1.1、定义类
语法:
修饰符 class 类名 { //属性声明 //方法声明 }
1 /** 2 * 测试定义类 3 * @author 林 4 * 5 */ 6 public class TestStudent { 7 String name; //属性声明 8 int age; 9 10 void study() { //方法声明 11 System.out.println("学习中"); 12 } 13 }
1.2、创建对象
语法:
修饰符 数据类型 属性名 = 初始化值 ;
// 测试创建对象 TestStudent s=new TestStudent();
1.3、属性
数据类型 | 初始化默认值 |
---|---|
整型 | 0 |
浮点型 | 0.0 |
字符型 | '\u0000' |
布尔型 | false |
所有引用类型 | null |
Java 语言中除基本类型之外的变量类型都称之为引用类型。
1.4、修饰符
同一个类 | 同一个包 | 子类 | 所有类 | |
---|---|---|---|---|
private | √ | × | × | × |
default(默认) | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
1.5、内存分析
堆( Heap):存储对象实例
栈( Stack): 存储局部变量
方法区(Method Area) :存储类信息、 常量、 静态变量、 静态方法、代码
二、方法
语法:
修饰符 方法返回类型 方法名(方法参数列表) { 若干方法语句; return 方法返回值; }
2.1、参数
方法可以包含0个或任意个参数。方法参数用于接收传递给方法的变量值。调用方法时,必须严格按照参数的定义一一传递。
可变参数用类型...
定义,可变参数相当于数组类型。
1 class Group { 2 String[] names; 3 4 public void setNames(String... names) { 5 this.names = names; 6 } 7 }
// 测试可变参数 Group g=new Group(); g.setNames(); //传0个参数 g.setNames("林一"); //传1个参数 g.setNames("林一","林二"); //传2个参数
【1】基本类型参数传递,传递的是数值。
1 // 测试基本类型参数传递 2 public class Main { 3 public static void main(String[] args) { 4 Person p = new Person(); 5 int n = 15; 6 p.setAge(n); //setAge()方法获得的参数,复制了n的值给p.age,后面n改变不影响p.age 7 System.out.println(p.getAge()); // 打印15 8 n = 20; 9 System.out.println(p.getAge()); // 打印15 10 } 11 } 12 13 class Person { 14 private int age; 15 16 public int getAge() { 17 return this.age; 18 } 19 20 public void setAge(int age) { 21 this.age = age; 22 } 23 }
【2】引用类型参数的传递,传递的是对象地址。
1 // 测试引用类型参数的传递 2 public class TestMethod { 3 public static void main(String[] args) { 4 Person p=new Person(); 5 String[] f=new String[] {"林一","林二"}; 6 p.setName(f); //数组是一个对象,传入数组只是传引用地址 7 System.out.println(p.getName()); 8 f[1]="林三"; //修改数组元素 9 System.out.println(p.getName()); //引用地址没变,数组元素改变,结果也改变 10 } 11 } 12 13 class Person{ 14 private String[] name; 15 16 public String getName() { 17 return this.name[0]+" "+this.name[1]; 18 } 19 20 public void setName(String[] name) { 21 this.name=name; 22 } 23 }
2.2、方法重载(Overload)
方法名相同,但各自的参数不同,称为方法重载。
注意:方法重载的返回值类型通常都是相同的。
方法重载的目的是,功能类似的方法使用同一名字,更容易记住,因此,调用起来更简单。
2.3、构造方法
构造方法(constructor),是一个创建对象时被自动调用的特殊方法,目的是对象的初始化。
【构造方法要点】:
-
通过new关键字调用。
-
构造方法有返回值,但不能定义返回值类型,不能在构造器里使用return返回某个值。
-
如没有定义构造方法,则编译器会自动定义一个无参的构造方法。如已定义则编译器不会自动添加。
-
构造器的方法名必须和类名一致。
1 package com.test; 2 /** 3 * 测试定义构造方法 4 * @author 林 5 * 6 */ 7 public class TestStu { 8 public static void main(String[] args) { 9 Stu s=new Stu("林一",17); // 创建对象会自动调用构造方法 10 System.out.println(s.getName()); 11 } 12 } 13 14 class Stu{ 15 private String name; 16 private int age; 17 18 public Stu(String name,int age) { //定义构造方法 19 this.name=name; 20 this.age=age; 21 } 22 23 public String getName() { 24 return this.name; 25 } 26 27 public int getAge() { 28 return this.age; 29 } 30 }
【1】默认构造方法
如一个类没有定义构造方法,编译器会自动为我们生成一个默认构造方法,它没有参数,也没有执行语句。
如自定义了一个构造方法,那么,编译器就不再自动创建默认构造方法。
【2】构造方法重载(Overload)
构造方法重载,根据不同参数区别不同得构造方法。
1 /* 测试构造方法重载 */ 2 class Person { 3 private String name; 4 private int age; 5 6 public Person(String name, int age) { 7 this.name = name; 8 this.age = age; 9 } 10 11 public Person(String name) { 12 this.name = name; 13 this.age = 12; 14 } 15 16 public Person() { 17 } 18 }
2.4、equals与==方法
Object 的 equals 方法默认就是比较两个对象的hashcode,是同一个对象的引用时返回 true 否则返回 false。
==代表比较双方是否相同。如果是基本类型则表示值相等,如果是引用类型则表示地址相等即是同一个对象。
【eclipse把光标放String类,按ctrl键+点击鼠标左键看类源码】
1 package com.test; 2 3 /** 4 * 测试equals与==方法 5 * @author 林 6 * 7 */ 8 9 public class TestEquals { 10 public static void main(String[] args) { 11 Person p1=new Person(); 12 Person p2=new Person(); 13 System.out.println(p1==p2); //false 14 System.out.println(p1.equals(p2)); //false 15 16 String s1=new String(); 17 String s2=new String(); 18 System.out.println(s1==s2); //false 19 System.out.println(s1.equals(s2)); //true,equals重构过 20 } 21 } 22 23 class Person{ 24 int id; 25 String name; 26 public void showName() { 27 System.out.println(id+" "+name); 28 } 29 }
2.5、toString方法
Object类中定义有public String toString()方法,其返回值是 String 类型。
Object类中toString方法的源码为:
1 public String toString() { 2 return getClass().getName() + "@" + Integer.toHexString(hashCode()); 3 }
1 package com.test; 2 /** 3 * 测试toString默认输出值 4 * @author 林 5 * 6 */ 7 public class TestToString { 8 public static void main(String[] args) { 9 Per p=new Per(); 10 System.out.println(p); 11 } 12 } 13 14 class Per{ 15 String name; 16 int age; 17 }
执行结果: com.test.Per@15db9742
1 package com.test; 2 /** 3 * 测试重写toString方法 4 * @author 林 5 * 6 */ 7 public class TestToString { 8 public static void main(String[] args) { 9 Per p=new Per(); 10 p.name="林一"; 11 p.age=18; 12 System.out.println(p); 13 } 14 } 15 16 class Per{ 17 String name; 18 int age; 19 @Override 20 public String toString() { //重写toString方法 21 return name+" "+age; 22 } 23 }
三、关键字
3.1、this关键字
在方法内部,可以使用一个隐含的变量this
,它始终指向当前对象。因此,通过this.field
就可以访问当前对象的字段。
如果没有命名冲突,可以省略this
。
1 class Person { 2 private String name; 3 public String getName() { 4 return name; // 相当于this.name 5 } 6 }
如果有局部变量和字段重名,那么局部变量优先级更高,就必须加上this
。
1 class Person { 2 private String name; 3 public void setName(String name) { 4 this.name = name; // this不可少,this.name为成员变量 5 } 6 }
3.2、super关键字
super
关键字表示父类(超类)。子类引用父类的字段时,可以用super.fieldName
。
1 class Student extends Person { 2 public String hello() { 3 return "Hello, " + super.name; //调用父类属性 4 } 5 }
1 class Student extends Person { 2 protected int score; 3 public Student(String name, int age, int score) { 4 super(name, age); // 调用父类的构造方法Person(String, int) 5 this.score = score; 6 } 7 }
3.3、static关键字
static声明的成员变量为静态属性。
static声明的方法为静态方法
-
静态属性被该类的所有实例共享,在类被载入时被显式初始化。
-
静态属性使用 “类名.类属性” 调用。
-
静态方法不需要对象, 就可以调用(如:类名.方法名)。
-
调用静态方法时, 不会将对象的引用传递给它, 所以在static方法中不可访问非static的成员。
-
静态方法不能以任何方式引用this和super关键字。
1 /** 2 * 测试static关键字 3 * @author 林 4 * 5 */ 6 public class TestStatic { 7 int a; 8 static int width; //静态成员变量、类属性 9 10 static void gg() { //静态方法 11 System.out.println("gg"); 12 } 13 14 void tt() { //普通方法 15 System.out.println("tt"); 16 } 17 18 public static void main(String[] args) { //java程序执行入口 19 TestStatic hi=new TestStatic(); 20 TestStatic.width=2; //调用静态成员变量 21 TestStatic.gg(); //调用静态方法 22 } 23 }
【1】静态初始化块
-
如果希望加载后, 对整个类进行某些初始化操作, 可以使用static初始化块。
-
类第一次被载入时先执行static代码块; 类多次载入时, static代码块只执行一次; Static经常用来进行static变量的初始化。
-
经常用来进行static变量的初始化。
-
静态初始化块中不能访问非static成员。
1 /** 2 * 测试静态初始化块 3 * @author 海 4 * 5 */ 6 public class TestStaticBlock { 7 static { //静态初始化块,类载入时加载 8 System.out.println("静态初始化块"); 9 } 10 11 public static void main(String[] args) { 12 System.out.println("main方法"); 13 } 14 }
3.4、final关键字
final作用:
-
修饰变量: 被他修饰的变量不可改变。一旦赋了初值,就不能被重新赋值。
-
修饰方法:该方法不可被子类重写。但是可以被重载。
-
修饰类: 修饰的类不能被继承。比如:Math、String等。
四、垃圾回收机制
五、包
包机制是Java中管理类的重要手段,通过包我们很容易对解决类重名的问题,也可以实现对类的有效管理。
【二个要点】:
-
通常是类的第一句非注释性语句。
-
包名:域名倒着写即可,再加上模块名,便于内部管理类。
1 package com.test; 2 3 public class TestPerson { 4 5 }
5.1、常用包
Java常用包 | 说明 |
---|---|
java.lang | 包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。 |
java.awt | 包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。 |
java.net | 包含执行与网络相关的操作的类。 |
java.io | 包含能提供多种输入/输出功能的类。 |
java.util | 包含一些实用工具类,如定义系统特性、使用与日期日历相关的函数。 |
5.2、导入类
【要点】:
-
Java会默认导入java.lang包下所有的类,因此这些类我们可以直接使用。
-
如果导入两个同名的类,只能用包名+类名来显示调用相关类。
1 package com.test; 2 /** 3 * 测试导入同名类的处理 4 * @author 海 5 * 6 */ 7 8 import java.sql.Date; 9 import java.util.*; 10 11 public class Test { 12 public static void main(String[] args) { 13 Date now; 14 java.util.Date now2=new java.util.Date(); //java.util.Date和java.sql.Date类同名,需要完整路径 15 System.out.println(now2); 16 Scanner input=new Scanner(System.in); 17 } 18 }
5.3、静态导入
静态导入:其作用是用于导入指定类的静态属性,这样可以直接使用静态属性。
1 package com.test; 2 3 /** 4 * 测试静态属性导入的使用 5 * @author 海 6 * 7 */ 8 9 import static java.lang.Math.*; //导入Math类的所有静态属性 10 import static java.lang.Math.PI; 11 12 public class Test { 13 public static void main(String[] args) { 14 System.out.println(PI); 15 System.out.println(random()); 16 } 17 }