1、final
1. 修饰变量:
被他修饰的变量不可改变。一旦赋了初值,就不能被重新赋值。
2. 修饰方法
该方法不可被子类重写。但是可以被重载!
3. 修饰类
修饰的类不能被继承。比如:Math、String等。
其中的方法自动成为final方法,而不包括字段。
2、static
1)static方法:
在一个类中有个方法A,其他方法(比如B)想要调用A,那么就必须把A定义为static method
2)static变量:
如果想静态方法想要使用一个方法体外的成员变量(属于类的),那么这个成员变量就必须是静态变量!
Java中,static是不允许用来修饰局部变量
3)static代码块
优化程序性能,类中可以有多个static块.每一次类被JVM加载到内存中的时候,会优先地加载静态代码块.
只需要进行一次的初始化操作都放在static代码块中进行
4) static修饰内部类(inner class)
想要修饰一个类,这个要被修饰的类就必须是另外一个类的外部类.
java中,一个类是可以允许另外一个内部类在类中定义的,按规定,这种内部类才能被static修饰.
如果,外部类也用static来修饰的话,那么将毫无意义,因为类若是被使用,那么迟早是要被加载一次的,用static修饰它就是一种对资源的浪费.所以,java语法也不允许.
3、重载
有相同的名字、不同的参数便出现了重载,要完整的描述一个方法,需要指定方法名以及参数类型。这叫做方法的签名。返回类型不是方法签名的一部分。也就是说,不能有两个名字相同、参数类型相同但拥有不同返回类型的方法。
4、默认字段初始化
如果在构造器中没有显式地为字段设置初值,那么就会被自动地赋为默认值:数值为0,布尔值为false,对象引用为null。这是字段与局部变量地一个重要区别。方法中的局部变量必须明确地初始化。
仅当类没有任何其他构造器的时候,你才会得到一个默认的无参构造器。编写类的时候,如果写了自己的构造器,要想调用new ClassName()就必须提供一个无参的构造器。当然,如果希望所有字段被赋予默认值,只需要提供一下代码:
public ClassName()
{
}
5、显式字段初始化
public class Employee {
private static int nextId;
private int id=assignId();
private static int assignId()
{
return ++nextId;
}
}
6、调用另一个构造器
public Employee(double s)
{
this("Employee #"+nextId,s);
nextId++;
}
7、静态绑定
如果是private方法,static方法,final方法或者构造器,那么编译器将可以准确地知道应该调用哪个方法。这称为静态绑定。于此对应的是,如果要调用地方法依赖于隐式参数地实际类型,那么必须在运行时动态绑定。
8、内联
如果一个方法没有被覆盖而且很简短、被频繁的调用,那么Java虚拟机的即时编译器将会将这个方法进行内联处理。
如果虚拟机加载了另外一个子类,而这个子类覆盖了一个内联方法,优化器将取消对这个方法的内联。
9、多态
在实例化子类对象时,如果父类的实例引用了子类的对象(多态),例如:父类 实例 = new 子类()
那么该引用在调用父类的方法时遵循以下原则
1 该实例 可以调用父类中特有的方法。(该方法未被子类重写)
2 该实例如果调用父类中的方法,若该方法被子类重写,则一定调用的是在子类中重写后的该方法。
3 该实例不可以调用父类中没有的方法。(该方法子类特有)
如果通过强制转换,将父类引用赋给子类变量,这时候会调用子类的重写方法。
在多态机制下,父类引用只能调用子类的重写方法,除此之外,无法调用子类的任何方法。
父类:
package test;
public class Employee {
private static int nextId;
protected int x;
public void show()
{
System.out.println("show in Employee");
}
private void f()
{
System.out.println("this is a private function in Employee");
}
public void f3()
{
System.out.println("this is a public function in Employee");
}
}
子类
package test2;
import test.Employee;
public class Manager extends Employee {
public void show()
{
System.out.println("show in Manager");
}
private void f1()
{
System.out.println("this is a private function in Manager");
}
public void f2()
{
System.out.println("this is a public function in Manager");
}
public static void main(String[] args) {
Manager manager=new Manager();
manager.show();
Employee employee=new Employee();
employee.show();
/* Manager manager1=new Employee();//error 用父类对象实例一个子类变量,错误 */
Employee employee1=new Manager();//用子类对象实例一个父类变量,正确
employee1.show();//用子类对象实例一个父类变量,调用子类的方法
/*employee.f1(); 父类无法访问子类的私有方法*/
/*employee.f2(); 父类无法访问子类的公共方法*/
/*父类无法访问子类的任何方法*/
employee=manager;
employee.show();//将子类引用赋给父类变量,调用子类的重写方法
/*employee.f1();
employee.f2();
将子类的引用赋给父类变量后,父类依然无法访问子类的任何方法*/
employee.f3();//将子类方法赋给父类变量后,能够调用父类的方法,但是依然无法调用子类的任何方法
/*manager.f();//error 调用父类的私有方法,错误 */
manager=(Manager)employee;
manager.show();//将父类引用赋给子类变量,调用子类的方法
/* manager.f();//error 将父类的引用赋给子类变量再调用父类的私有方法,错误 */
}
}
10、instanceof
判断其左边对象是否为其右边类的实例
System.out.println(manager instanceof Employee);//true
System.out.println(employee instanceof Manager);//false
11、native
简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern “C”告知C++编译器去调用一个C的函数。
native是与C++联合开发的时候用的!使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。 这些函数的实现体在DLL中,JDK的源代码中并不包含,你应该是看不到的。对于不同的平台它们也是不同的。这也是java的底层机制,实际上java就是在不同的平台上调用不同的native方法实现对操作系统的访问的。总而言之:
native 是用做java 和其他语言(如c++)进行协作时使用的,也就是native 后的函数的实现不是用java写的。
既然都不是java,那就别管它的源代码了,我们只需要知道这个方法已经被实现即可。
native的意思就是通知操作系统, 这个函数你必须给我实现,因为我要使用。 所以native关键字的函数都是操作系统实现的, java只能调用。
java是跨平台的语言,既然是跨了平台,所付出的代价就是牺牲一些对底层的控制,而java要实现对底层的控制,就需要一些其他语言的帮助,这个就是native的作用了。
12、枚举类
package test2;
import com.sun.javaws.IconUtil;
public class ColorEnum {
enum Color {
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
// 普通方法
public static String getName(int index) {
for (Color c : Color.values()) {
if (c.getIndex() == index) {
return c.name;
}
}
return null;
}
// get set 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
public static void main(String[] args) {
System.out.println(Color.RED);//RED
System.out.println(Color.getName(2));//绿色S
Color color=Enum.valueOf(Color.class,"RED");
System.out.println(color.getIndex());//1
color.setIndex(2);
System.out.println(color);//RED
System.out.println(color.getName());//红色
System.out.println(Color.getName(2));//红色
color.setName("白色");
System.out.println(color);//RED
System.out.println(color.getName());//白色
System.out.println(color.getIndex());//2
}
}
set方法尽量不用。
13、打印一个类的全部信息
https://blog.csdn.net/qq_44627732/article/details/109351915
14、如果f是一个Field类型的对象,obj是某个包含f字段的类的对象,f.get(obj)将返回一个对象,其值为obj的当前字段值
package test2;
import test.Employee;
import java.lang.reflect.Field;
public class Manager extends Employee {
public Manager(String name) {
super(name);
}
public static void main(String[] args) {
var harry=new Employee("Harry Hacker");
Class cl=harry.getClass();
Field field=null;
try {
field=cl.getDeclaredField("name");
System.out.println(field.getName());//name
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
try {
Object v= field.get(harry);
System.out.println(v.getClass().getName());//java.lang.String
System.out.println(v);//Harry Hacker
} catch (IllegalAccessException e) {
e.printStackTrace();
}
try {
field.set(harry,"second harry");
System.out.println(harry.name);//second harry
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
15、使用反射编写泛型数组代码
package test2;
import org.w3c.dom.ls.LSOutput;
import test.Employee;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
public class Manager extends Employee {
public Manager(String name) {
super(name);
}
public static void main(String[] args) {
int[] a={1,2,3};
System.out.println(a.length);//3
a=(int[])CopyOf(a,10);
System.out.println(a.length);//10
}
public static Object CopyOf(Object a,int newLength)
{
Class cl=a.getClass();
if(!cl.isArray())
return null;
Class componentType=cl.getComponentType();
int length= Array.getLength(a);
Object newArray=Array.newInstance(componentType,newLength);
System.arraycopy(a,0,newArray,0,Math.min(length,newLength));
return njiewArray;
}
}
16、接口
接口中所有的方法都默认是public,在实现接口时,必须把方法声明为public,否则,编译器将认为这个方法的访问属性是包可见性,这是类的默认访问属性,之后编译器将报错。
接口中的字段默认是public static final