一个Java文件中定义多个类
- 只能由一个public类
- 其他的非public类只能是默认修饰符,可以有多个非public类
- 在public类里可以访问非public里的类(因为在同一个包下)
package com.hqyj;
//一个源文件中只能有一个public类,类名跟文件名相同
public class A {
public static void main(String[] args) {
B b = new B();
b.btest();
}
}
//一个源文件中还可以有其他的非public(只能是默认修饰符)的类
class B{
public void btest(){
System.out.println("B类方内部类法");
}
}
内部类
定义在类中的类称为内部类
作用是封装,一般是自己使用的类定义为内部类,不想让别人知道或者使用而定义的类
成员内部类(定义在大括号里面)
-
内部类定义为一个成员(跟成员变量或方法同一级)
-
内部类可以用任意访问修饰符(一般起封装作用的话用private)
-
内部类和外部类之间可以相互访问,即便是private修饰的也可以
-
内部类的初始化要借助外部类的对象:
Inner inner = outre.new Inner();
public class Outre {
private String id = "abcd123";
public void funOtre(){
System.out.println("外部类的方法");
}
public static void main(String[] args) {
Outre outre = new Outre();
outre.funOtre();
Inner inner = outre.new Inner();
inner.funInner();
System.out.println(inner.name);
}
private class Inner{
public Inner() {
System.out.println("Inner的构造方法");
}
private String name = "姓名";
private void funInner(){
System.out.println(id);
System.out.println("内部类的方法");
funOtre();
}
}
}
静态内部类
- 如果成员内部类是静态的,创建内部对象的方式: Inner inner = new OuterStatic.Inner();
- 内部类中只能访问外部类的静态属性和方法
- 在外部类中可以通过内部类的类名直接访问内部类的静态属性和方法
package com.hqyj;
public class OuterStatic {
private String nameOuter = "外部类的属性";
private static String nameOuterStatic = "外部类的静态属性";
private void funOuter(){
System.out.println("外部类的方法");
// System.out.println(nameInner);//不能访问内部类的属性
//funInner(); //不能访问内部类的方法
}
private static void funStaticOuter(){
System.out.println("外部类的静态方法");
System.out.println(Inner.nameStaticInner);
Inner.funStaticInner();
}
private static class Inner{
private String nameInner = "内部类的属性";
private static String nameStaticInner = "内部类的静态属性";
private void funInner(){
System.out.println("内部类的方法");
System.out.println(nameOuterStatic);
funStaticOuter();
}
private static void funStaticInner(){
System.out.println("内部类的静态方法");
System.out.println(nameOuterStatic);
funStaticOuter();
}
}
public static void main(String[] args) {
OuterStatic outer = new OuterStatic();
outer.funOuter();
Inner inner = new OuterStatic.Inner();
inner.funInner();
System.out.println(Inner.nameStaticInner);
OuterStatic.Inner.funStaticInner();
}
}
局部内部类(定义在方法中)
- 内部类定义在方法中
- 内部类的创建只能在这个方法中,创建内部类的方法: Inner inner = new Inner();
- 内部类可以直接访问外部类的属性和方法,外部类不能直接访问内部类的属性和方法,但是可以通过内部类的对象去访问
package com.hqyj;
public class OuterLocal {
private String nameOuter = "外部类的属性";
private void fun2Outer(){
}
private void funOuter(){
System.out.println("外部类方法");
class Inner{
private String nameInner = "内部类的属性";
private void funInner(){
System.out.println("内部类的方法");
//内部类可以调用外部类的属性
System.out.println(nameOuter);
//内部类可以调用外部类的方法
fun2Outer();
}
}
//System.out.println(nameInner);
//外部类不能直接访问内部类的属性
//funInner();
//外部类不能直接访问内部类的方法
Inner inner = new Inner();
inner.funInner();
System.out.println(inner.nameInner);
}
public static void main(String[] args) {
OuterLocal outer = new OuterLocal();
outer.funOuter();
}
}
匿名内部类
类只用一次,所以没有类名
一般用在接口作为方法参数的情况
- USB接口
package usb;
public interface USB {
void work();
}
-
Computer类
有一个方法是USB接口类型
package usb; public class Cmputer { public void useUSB(USB usb){ usb.work(); } }
-
调用接口参数的方法时,直接实现接口
这个接口的实现类没有名字,所以叫匿名类,其它地方不可能用到它
package usb;
public class CmputerTest {
public static void main(String[] args) {
Cmputer cmputer = new Cmputer();
cmputer.useUSB(new USB() {
@Override
public void work() {
System.out.println("鼠标正在使用....");
}
});
}
}
枚举
- 枚举的定义
package enumer;
public enum Season {
SPRING,SUNNER,AUTMN,WINTER
}
- 枚举的使用
package enumer;
public class SeasonTest {
public static void main(String[] args) {
Season spring = Season.SPRING;
switch (spring){
case SPRING:
System.out.println("春天播种");
break;
case SUNNER:
System.out.println("夏天施肥");
break;
case AUTMN:
System.out.println("秋天收获");
break;
case WINTER:
System.out.println("冬天过冬");
break;
}
}
}
类的方法
方法是类的行为,通过方法执行一段代码,完成特定的功能
方法的定义:
[public] [static] [abstract] [final] 返回类型 方法名(类型 参数名,类型 参数名){
//方法体代码
}
方法的特性:
- 除构造方法外,所有的方法都有返回类型,如果不需要返回类型,则方法的返回类型为void
- 如果有返回值,方法必须有return语句(保证每一个分支都有return语句),return语句后不能再有其他代码
- 方法可以有参数,无参数,还可以是不定长的参数
- 类型后面有三个点参数叫做可变长参数,可变长参数只能是最后一个参数,可变长参数在方法中可以当成数组处理
- 方法相同,参数不同,构成重载。可变长参数和固定长参数同时存在,优先调用固定参数的方法
public class MethodDemo {
public void fun1(){
System.out.println("没有返回值,返回类型是void");
}
//有返回类型,方法体必须有return语句,返回的内容必须限返回类型一致
//保证每一个分支都有返回语句
public String getName(){
String name = "";
if(3 > 2){
name = "姓名";
}else{
}
return name;
/* if(3 > 2){
System.out.println("姓名");
}else{
return "";
}*/
}
//固定个数的参数
public int sum(int a,int b){
System.out.println("a,b");
return a + b;
}
//类型后面有三个点参数叫做可变长参数
//可变长参数只能是最后一个参数
//可变参数可以当成数组处理
public int sum(int a,int...b){
int sum = 1;
sum += a;
for(int temp:b){
sum += temp;
}
return sum;
}
public static void main(String[] args) {
MethodDemo methodDemo = new MethodDemo();
System.out.println(methodDemo.sum(1,2,2,3,3,3));
}
}
传值调用和引用调用
形参:形式参数,方法定义时给出的参数名
public int sum(int a,int b){
}
//a,b就叫形参
实参:实际参数,调用方法时传的变量
int m = 2 ,n = 3;
//m,n叫实参
sum(m,n);
-
传值调用
当参数类型为基本类型时,在方法里面改变形参的值,不影响实参(理解为调用方法时copy了一份参数)
//定义方法 public int sum(int a,int b){ int sum = a + b; a++; b--; return a + b; } //调用方法 int x = 10; int y = 20; int sum = methodDemo.sum(x,y); System.out.println(sum); System.out.println(x + " " + y);//x:10 y:20
-
传引用调用
当参数类型为引用类型(类,接口,数组),在方法里面改变这个对象的值,实参的对象的值也跟着改变(因为它们指向的时堆中的同一个引用实例)
方法类
package methods; public class Student { private String name; int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
测试类
package methods; public class StudentTest { public static void main(String[] args) { StudentTest test = new StudentTest(); Student student = new Student("张三",23); test.updateStudent(student); System.out.println(student); } public void updateStudent(Student stu){ stu.setAge(25); } }
方法的递归调用
方法里面调用自己,替代循环代码
理解递归调用,知道方法被调用会在栈里压入一个方法帧,直到最后一次调用方法结束,再依次出栈,返回值
/**
* 递归调用
*/
public class Recursion {
public static void main(String[] args) {
Recursion recursion = new Recursion();
System.out.println(recursion.sumone2n(100));
System.out.println(recursion.factorial(5));
System.out.println(recursion.fibonacci(12));
}
// 求1~n的和的递归方法
public int sumone2n(int n){
int sum = n;
if (n == 1){
return 1;
}else {
return n + sumone2n(n - 1);
}
}
// 求n的阶乘的递归方法
public int factorial(int n){
if (n == 0) {
return 1;
}else {
return n * factorial(n-1);
}
}
//斐波拉契数列用递归
public long fibonacci(int n){
if (n == 1 || n == 2) {
return 1;
}else{
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
}