方法和封装的概念
构造方法的基本概念------------------------------
class 类名{
类名(形参列表){
构造方法体;
}
}
class Person{
Person(){
}
}
构造方法名与类名完全相同并且没有返回值类型,连void都不许有
默认构造方法:当一个类中没有定义任何构造方法时,编译器会自动添加一个无参空构造即无参数的构造方法
叫做默认/缺省构造方法,如:
Person(){};
若类中出现了构造方法,则编译器不再提供任何形式的构造方法
构造方法的好处可以在构造方法里进行自己成员变量的操作,但默认的构造方法就没有这样的操作
构造方法的作用:使用new关键字创建对象时会自动调用构造方法实现成员变量初始化工作
public class Personn{
String name;
int age;
Personn(String s,int i){
name = s;
age = i;
}
void show(){
this.grow();
System.out.println("我是" + name + ",今年" + age + "岁了!");
}
void grow(){
age++;
}
void grow(int i){
age += i;
}
Personn getPersonn(){
return this;
}
public static void main(String[] args){
Personn p1 = new Personn("张飞",30);
p1.show();
Personn p2 = new Personn("关羽",40);
p2.show();
System.out.println("--------------------------------------------------------------------");
p2.grow();
p2.show();
p2.grow(2);
p2.show();
System.out.println("--------------------------------------------------------------------");
Personn pp = p1.getPersonn();
System.out.println("p1 = " + p1);
System.out.println("pp = " + pp);
pp.show();
}
}
案例题目------------------------------
编程实现Pointt类的定义并向Pointt类添加构造方法
Pointt()默认创建原点对象
Pointt(int i,int j)根据参数创建点对象
public class Pointt{
int x;
int y;
Pointt(){
}
Pointt(int i,int j){
x = i;
y = j;
}
void show(){
System.out.println("横坐标是:" + x + ",纵坐标是:" + y);
}
void up(){
y--;
}
void up(int dy){
y -= dy;
}
public static void main(String[] args){
Pointt p1 = new Pointt();
p1.show();
Pointt p2 = new Pointt(3,5);
p2.show();
System.out.println("--------------------------------------------------------------------");
p2.up();
p2.show();
p2.up(2);
p2.show();
}
}
重载的概念和体现形式------------------------------
若方法名称相同,参数列表不同,这样的方法之间构成重载关系(Overload)
方法重载的主要形式体现在:参数的个数不同,参数的类型不同,参数的顺序不同,与返回值类型和形参变量名无关
但建议返回值类型最好相同,因为若不同,那么我们就要处理返回值,而相同时,则不用非常麻烦的处理
判断方法能否构成重载的核心:调用方法时能否加以区分
练习题目------------------------------
编程实现Pointt类添加重载的成员方法
up()实现纵坐标减1的功能
up(int dy)实现纵坐标减去参数指定数值的功能
测试重载方法的调用规则
public class Pointt{
int x;
int y;
Pointt(){
}
Pointt(int i,int j){
x = i;
y = j;
}
void show(){
System.out.println("横坐标是:" + x + ",纵坐标是:" + y);
}
void up(){
y--;
}
void up(int dy){
y -= dy;
}
public static void main(String[] args){
Pointt p1 = new Pointt();
p1.show();
Pointt p2 = new Pointt(3,5);
p2.show();
System.out.println("--------------------------------------------------------------------");
p2.up();
p2.show();
p2.up(2);
p2.show();
}
}
重载的实际意义------------------------------
方法重载的实际意义在于调用者只需要记住一个方法名就可以调用各种不同的版本,来实现各种不同的功能
如:java.io.PrintStream类中的println方法
就类似于我们打印变量时的操作,变量可以是很多类型,那个也是重载,如:System.out.println()
public class OverloadTest{
void show(){
System.out.println("show()");
}
void show(int i){
System.out.println("show(int)");
}
void show(int i,double d){
System.out.println("show(int,double)");
}
void show(int i,int j){
System.out.println("show(int,int)");
}
void show(double i,int j){
System.out.println("show(double,int)");
}
public static void main(String[] args){
OverloadTest ot = new OverloadTest();
ot.show();
ot.show(66);
ot.show(66,3.14);
ot.show(66,3);
ot.show(3.14,66);
}
}
this的基本概念------------------------------
若在构造方法中出现了this关键字,则代表当前正在构造的对象
若成员方法中出现了this关键字,则代表当前正在调用的对象
this关键字本质上就是当前类类型的引用变量
System.out.println("我是" + name + ",今年" + age + "岁了!");
this关键字的工作原理------------------------------
在构造方法中和成员方法中访问成员变量时,编译器会加上this.的前缀
而this.相当于汉语中的"我的",当不同的对象调用同一个方法时,由于调用方法的对象不同导致this关键字不同
从而this.方式访问的结果也随之不同
this使用方式------------------------------
public class test{
int i;
String s;
test(int i,String s){
this.i = i;
this.s = s;
}
}
当局部变量名与成员变量名相同时,在方法体中会优先使用局部变量(就近原则)
若希望使用成员变量,则需要在成员变量的前面加上this.前缀,明确要求该变量是成员变量(重中之重)
this关键字除了可以通过this.的方式调用成员变量和成员方法外,还可以作为方法的返回值(重点)
在构造方法的第一行可以通过this()的方式来调用本类中的其他构造方法(了解)
至于为什么必须是第一行,因为若不为第一行的话,在前面就对类的一些东西进行操作,如成员变量
那么操作完后,再用这个this调用构造方法的话,就会重复操作,即就规定了只能第一行
public class ThisTest {
ThisTest(){
System.out.println("构造方法中:this = " + this);
}
void show(){
System.out.println("成员方法中:this = " +this);
}
public static void main(String[] args) {
ThisTest tt = new ThisTest();
tt.show();
System.out.println("main方法中:tt = " + tt);
}
}
注意:this是在执行时,才会有的,即谁执行就代表谁,如a.fa(),就代表a,new aa()就代表他这个地址
public class Boy {
String name;
Boy(){
System.out.println("无参构造方法");
}
Boy(String name){
this();
System.out.println("-------有参构造方法");
this.name = name;
}
void show(){
System.out.println("我的名字是:" + name);
}
public static void main(String[] args) {
Boy b1 = new Boy();
b1.show();
System.out.println("--------------------------------------------------------------------");
Boy b2 = new Boy("张飞");
b2.show();
}
}
注意事项------------------------------
引用类型变量用于存放对象的地址,可以给引用类型赋值为null,表示不指向任何对象
当某个引用类型变量为null时,无法对对象实施访问(因为它没有指向任何对象)
此时,如果通过引用访问成员变量或调用方法,会产生NullPointerException异常
案例题目------------------------------
编程实现参数n的阶乘并返回,所谓阶乘就是从1累乘到n的结果
public class JieChengTest{
int show(int n){
if(1 == n) return 1;
return n * show(n-1);
}
public static void main(String[] args) {
JieChengTest jct = new JieChengTest();
int res = jct.show(5);
System.out.println("最终的计算结果是:" + res);
}
}
递归的基本概念------------------------------
递归本质就是指在方法体的内部直接或间接调用当前方法自身的形式
使用递归必须有递归的规律以及退出条件
使用递归必须使得问题简单化而不是复杂化
若递归影响到程序的执行性能,则使用递归取代之
案例题目------------------------------
编程实现费式数列中第n项的数值并返回
费式数列:1 1 2 3 5 8 13 21 …
public class FeeTest{
int show(int n){
int ia = 1;
int ib = 1;
for(int i= 3; i<=n; i++){
int ic = ia + ib;
ia = ib;
ib = ic;
}
return ib;
}
public static void main(String[] args) {
FeeTest ft = new FeeTest();
int res = ft.show(5);
System.out.println("最终结果是:" + res);
}
}
将上述代码拆分
public class Fee{
int show(int n){
int ia = 1;
int ib = 1;
for(int i= 3; i<=n; i++){
int ic = ia + ib;
ia = ib;
ib = ic;
}
return ib;
}
}
public class FeeTest{
public static void main(String[] args) {
Fee ft = new Fee();
int res = ft.show(5);
System.out.println("最终结果是:" + res);
}
}
上述可以分开调用,编译FeeTest类的同时main方法的Fee类也会编译,最后执行FeeTest类可以得到相应结果
但这里不可以直接用java FeeTest.java运行了,因为他只可对该类操作,即Fee的类不识别,所以要编译运行
而用java FeeTest.java时,可以一步到位(编译和执行一起操作)
他会先检查你是否编译,若你编译过了,则会报错,因为他必须一步到位,不可有已经操作的地方
但若你的Fee类编译了,即识别了,那么由于java FeeTest.java是一步到位的,那么也会报错
从上述可知,递归需要执行很多次,会影响性能,即使用递推
封装的概念------------------------------
通常情况下可以在测试类给成员变量赋值一些合法但不合理的数值,无论是编译阶段还是运行阶段都不会报错或者给出提示
此时与现实生活不符
为了避免上述错误的发生,就需要对成员变量进行密封包装处理
来隐藏成员变量的细节以及保证成员变量数值的合理性,该机制就叫做封装
封装的实现流程------------------------------
私有化成员变量,使用private关键字修饰
提供公有的get和set方法,并在方法体中进行合理值的判断
在构造方法中调用set方法进行合理值的判断
public class Student{
private int id;
private String name;
public Student(){
}
public Student(int id,String name){
setId(id);
setName(name);
}
public int getId(){
return id;
}
public void setId(int id){
if(id > 0){
this.id = id;
}else{
System.out.println(id + "学号不合理哦");
}
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
void show(){
System.out.println("我是:" + getName() + ",我的学号是:" + getId());
}
}
public class StudentTest{
public static void main(String[] args) {
Student s1 = new Student();
s1.setId(100);
s1.setName("张飞");
s1.show();
System.out.println("--------------------------------------------------------------------");
s1.setId(-1100);
s1.setName("张飞");
s1.show();
System.out.println("--------------------------------------------------------------------");
Student s2 = new Student(-1001,"关羽");
s2.show();
}
}
案例题目------------------------------
提示用户输入班级的学生人数以继每个学生的信息,学生的信息有:学号,姓名,最后分别打印出来
提示:Student[] arr = new Student[num];
import java.util.Scanner;
public class StudentTest2 {
public static void main(String[] args) {
System.out.println("请输入学生的人数:");
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
Student[] arr = new Student[num];
for(int i = 0; i < num; i++) {
System.out.println("请输入第" + (i+1) + "个学生的信息(学号 姓名):");
arr[i] = new Student(sc.nextInt(), sc.next());
}
System.out.println("-----------------------------------------------");
System.out.println("该班级的所有学生信息有:");
for(int i = 0; i < num; i++) {
arr[i].show();
}
}
}
JavaBean的概念------------------------------
JavaBean是一种Java语言写成的可重用组件,其他Java类可以通过反射机制发现和操作这些JavaBean的属性
JavaBean本质上就是符合以下标准的Java类
类是公共的
有一个无参的公共的构造器
有属性,且有对应的get,set方法
总结------------------------------
构造方法(重中之重)
语法格式、默认构造方法、实现成员变量的初始化
方法重载(重点)
概念、体现形式、实际意义
this关键字(原理)
概念、原理、使用方式
递归(难点)
概念、使用原则
封装(重中之重)
|