类是一类事物的统称,如人类、鸟类等;类是构造对象时所一类的规范,对象则是类的其中一种特定实现,如鸟类中又有麻雀、燕子、海鸥等,类中包含了所有鸟类的相同属性和行为,在Java中表现为属性和成员方法。
类名由多个单词组成时,每个单词首字母大写;命名成员变量/属性时,从第二个单词起每个首字母大写;成员方法命名方法与变量命名一致。
使用new关键字,调用类的构造函数创建类的对象。对象存储在内存空间中的堆。
数值类型的初始值都为0,布尔型默认值为false,引用类型为null.
class Person{
String name;
String sex;
int age;
public void action(){
System.out.println("吃饭睡觉打豆豆!");
}
private String info(String name,String sex,int age){
//这里的this表示当前类的属性
this.name=name;
this.sex=sex;
this.age=age;
}
}
返回值主要指从方法当中返回到方法体外的数据内容,可以是基本类型中的一种,也可以是引用类型。当该方法不需要返回任何数据内容时,返回值类型写void即可。
return 关键字可以返回具体的数据内容并结束当前方法。
public String info(int age){
return "这是返回的内容!";
}
一个方法的形参列表中最多只能声明一个可变长形参,并且需要放到参数列表的末尾。
class Test{
int age;
String name;
public String info(int age){
//这里的age为形参
return "这是返回的内容!"+age;
}
public int time(int num,String... a){
System.out.println(num);
for(int i=0,i<a.length;i++){
System.out.println("第"+i+"个元素"+a[i]);
}
}
}
public class Demo{
public static void main(String[] args){
Test t=new Test();
t.info(18);//这里的18为实参
}
}
1.基本数据类型的变量作为方法的参数传递时,形参变量数值的改变通常不会影响到实参变量的数值,因为两个变量有各自独立的内存空间;
2.引用数据类型的变量作为方法的参数传递时,形参变量指向内容的改变会影响到实参变量指向内容的数值,因为两个变量指向同一块内存空间
3.当引用数据类型的变量作为方法的参数传递时,若形参变量改变指向后再改变指定的内容,则通常不会影响到实参变量指向内容的改变,因为两个变量指向不同的内存空间
程序运行过程中所有的局部变量都被存储在栈中,JVM会为每一个被调用的方法分配一个与之对应的空间,该空间叫做栈帧。一个栈帧对应一个正在调用中的方法,栈帧中存储了方法的参数和局部变量等数据。方法调用结束后,对应的栈帧将会被消除。
class Bird{
public Bird(){
默认无参构造函数
//代码块
}
}
public class Demo{
public static void main(String[] args){
//使用new关键字创建对象时,会自动调用匹配的构造函数
Bird bird=new Bird();
}
}
class Calculate{
//返回值类型最好是相同的
public int add(int a,int b){
return a+b;
}
public int add(int a,double b){
return a+b;
}
public int add(double a,double b){
return a+b;
}
public int add(String a,String b){
return a+b;
}
}
从父类中继承下来的方法不满足子类的需求时,就需要在子类中重新写一个和父类一样的方法来覆盖从父类中继承下来的版本,该方式就叫做方法的重写
递归本质就是指在方法体的内部直接或间接调用当前方法自身的形式。
若在构造方法中出现了this关键字,则代表当前正在构造的对象。
若在成员方法中出现了this关键字,则代表当前正在调用的对象。
this关键字本质上就是当前类类型的引用变量。
在构造方法中和成员方法中访问成员变量时,编译器会加上this.的前缀,而this.相当于汉语中"我的",当不同的对象调用同一个方法时,由于调用方法的对象不同导致this关键字不同,从而this.方式访问的结果也就随之不同。
//这里以setXxx()方法为例子
public String setName(String name){
//this.name表示成员变量name
this.name=name;//用形参赋值给成员变量
}
public class Demo{
{
System.out.println("---这是非静态构造块!---");
}
static {
System.out.println("---这是静态构造块!---");
}
public Demo(){
System.out.println("---这是无参构造函数!---");
}
public Demo(String name){
System.out.println("---这是有参构造函数!---");
}
}
在继承关系中:
在某些特殊场合中,一个类对外提供且只提供一个对象时,这样的类叫做单例类,而设计单例的流程和思想叫做单例设计模式。
public SingleDemo{
//饿汉式
private static SingleDemo s=new SingleDemo();//一个类只有一份
private SingleDemo(){
} //使用private关键字修饰
//提供public方法访问
public SingleDemo getInstance(){
return s;
}
//懒汉式
private static SingleDemo s=null;
private SingleDemo(){
} //使用private关键字修饰
//提供public方法访问
public SingleDemo getInstance(){
if(null==s){
s=new SingleDemo();
}
return s;
}
}
两者区别在于饿汉式是调用getInstance()方法前就已经创建了对象,懒汉式是在调用方法后创建的类对象。
单例设计模式的实现方式有两种:饿汉式 和 懒汉式,在以后的开发中推荐饿汉式。
隐藏具体的实现细节,保证内部不受破坏。
成员变量用private修饰,即成员变量私有化。
生成共有的getXxx()、setXxx()方法来从外部访问和修改成员变量。
java中使用extends关键字来表示继承关系:
public class Son extends Father{
/*
Father类叫做超类、父类、基类。
Son类叫做派生类、子类、孩子类。
*/
}
使用继承提高了代码的复用性,可维护性及扩展性,是多态的前提条件。
如 Animal a=new Bird();
Animal a=new Dog();
题目描述:
1.编程实现Shape类的封装,特征有:横纵坐标,要求提供打印所有特征的方法。
2.编程实现Rect类的封装并继承自Shape类,特征有:长度和宽度。
3.编程实现ShapeRectTest类,在main方法中分别创建Shape和Rect类型对象并打印特征。
shape类
public class Shape {
public Shape(){
}
public Shape(int x,int y){
setX(x);
setY(y);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
private int x;
private int y;
public void show(){
System.out.println("Shape横坐标:"+x+"\t纵坐标:"+y);
}
}
Rect类
public class Rect extends Shape{
private int width;//矩形宽
private int length;//矩形长
public Rect(){
}
public Rect(int x,int y,int w,int l){
super(x,y);
setWidth(w);
setLength(l);
}
@Override
public void show() {
System.out.println("Rect矩形宽:"+width+"\t矩形长:"+length+"\tX:"+getX()+"\tY:"+getY());
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
}
ShapeRectTest类
public class ShapeRectTest {
public static void main(String[] args) {
Shape shape=new Shape(10,16);
Rect rect=new Rect(21,10,10,10);
shape.show();
rect.show();
Shape s=new Rect();
s.show();
}
}
输出如下所示:
//父类
public class Father{
public void smoke(){
//父亲独有的方法
System.out.println("父亲没事就点个烟抽~");
}
public static void show(){
System.out.println("父类的静态成员方法");
}
}
//子类
public class Son extends Father{
public void cry(){
System.out.println("儿子没奶吃就开始哭");
}
public static void show(){
System.out.println("子类的静态成员方法");
}
public static void main(String[] args){
Father f=new Son();
f.smoke();
//f.cry(); 父类引用指向子类对象 是无法调用子类独有方法的
((Son)f).cry();//强制类型转换后可以调用子类独有的方法
//静态方法也可以使用 对象名+"."的方式调用 但推荐使用类名.的方式调用
f.show();//输出结果为父类的静态方法
}
}
输出结果:
父亲没事就点个烟抽~
父类的静态成员方法
引用数据类型的转换分为自动类型转换和强制类型转换,有时也称作向上转型和向下转型。
1.自动类型转换主要指小类型向大类型的转换,也就是子类转为父类,也叫做向上转型。
2.强制类型转换主要指大类型向小类型的转换,也就是父类转为子类,也叫做向下转型或显式类型转换。
3.引用数据类型之间的转换必须发生在父子类之间,否则编译报错。 即不具有继承关系的类之间的转换时错误的。
4.若强转的目标类型并不是该引用真正指向的数据类型时则编译通过,运行阶段发生类型转换异常。
如下所示:
public class Father{
//代码块
}
public class Son extends Father{
//代码块
public static void main(String[] args){
Father f=new Son();
//引用变量f 实质上是 Son类型的引用变量,即真正指向的数据类型
Son s=(Son)f;
//
}
}
5.为了避免上述错误的发生,应该在强转之前进行判断,格式如下:
if(引用变量 instanceof 数据类型)判断引用变量指向的对象是否为后面的数据类型。
在于屏蔽不同子类的差异性实现通用的编程带来不同的
效果。
抽象方法主要是指使用abstract关键字修饰,没有方法体。
public abstract void show();
不能实例化的即无法创建对象,且使用abstract关键字修饰的类。
示例:
public abstract AbstractDemo{
private int ab;//成员变量
public void test(){
//成员方法
//代码块
}
//抽象方法
public abstract void show();
}
1.抽象类中可以有成员变量、构造方法、成员方法;
2.抽象类中可以没有抽象方法,也可以有抽象方法;
3.拥有抽象方法的类必须是抽象类,因此真正意义上的抽象类应该是4.具有抽象方法并且使用abstract关键字修饰的类。
抽象类的实际意义不在于创建对象而在于被继承。当一个类继承抽象类后必须重写抽象方法,否则该类也变成抽象类,也就是抽象类对子类具有强制性和规范性,因此叫做模板设计模式。
接口是特殊的抽象类,接口的所有方法均为抽象方法。使用interface关键字定义接口。