Suga
Suga

Reputation: 115

Unable to import com.sun.tools.javac.util.Pair

I'm new to java and currently using open-jdk and javac 21 and Eclipse IDE.

I'm trying to import om.sun.tools.javac.util.Pair and getting the error - "The type com.sun.tools.javac.util.Pair is not accessible".

Can someone please help how to install such modules/libraries. Googled a lot but couldn't find anything specific.

Openjdk version currently using - openjdk version "21" 2023-09-19 OpenJDK Runtime Environment (build 21+35-2513) OpenJDK 64-Bit Server VM (build 21+35-2513, mixed mode, sharing)

Upvotes: 1

Views: 119

Answers (2)

Slaw
Slaw

Reputation: 46181

The com.sun.tools.javac.util.Pair class is in a non-exported package of the jdk.compiler module. Not only does that mean the class is internal API and should not be relied upon, but like all jdk.* modules the API is JDK-specific (which may or may not be a problem for you). Note the class's documentation even states it's not supported:

/** A generic class for pairs.
 *
 *  <p><b>This is NOT part of any supported API.
 *  If you write code that depends on this, you do so at your own risk.
 *  This code and its internal interfaces are subject to change or
 *  deletion without notice.</b>
 */

See JEP 261: Module System and Understanding Java 9 Modules for more information.

You don't say why you need that class, nor do you indicate the jdk.compiler module is required by your application, so I'm going to assume your IDE listed it when you typed "Pair" and you simply tried to import it or something similar. If all you need is a "Pair" class, then you can easily implement one yourself using records.

package com.example;

public record Pair<T, U>(T first, U second) {

  // Not necessary, but included to be consistent with javac's Pair class
  public static <T, U> Pair<T, U> of(T first, U second) {
    return new Pair<>(first, second);
  }
}

Or if you happen to be using JavaFX, then make use of javafx.util.Pair. There are likely other utility libraries or frameworks out there that provide a similar class.

However, such a general Pair class could be considered bad practice. The advice I usually see is to create a data-holder class (nowadays typically a record) for specific purposes as needed. That way the class name and member names/types make perfect sense in context. See the answer by Basil Bourque for examples.


If you truly need to use the com.sun.tools.javac.util.Pair class for some reason, then you'll need to pass:

--add-exports jdk.compiler/com.sun.tools.javac.util=<targets>

At both compile-time and run-time. Replace <targets> with a comma-separated list of modules you want to export the package to. Use ALL-UNNAMED to export the package to the unnamed module (i.e., code loaded from the class-path instead of the module-path).

Search your IDE's documentation to see how to specify --add-exports as needed.

If your code is modular, you'll also need a requires jdk.compiler directive in your module-info descriptor. Or pass an appropriate --add-reads option, again both at compile-time and at run-time (prefer the requires approach).

Upvotes: 2

Basil Bourque
Basil Bourque

Reputation: 339837

As Commented…

Do not access the classes documented as being for internal use only.

This rule became enforceable by the compiler with the arrival of Java Platform Module System in Java 9.

For more details, see the excellent Answer by Slaw.


You can easily create your own “pair” class. Assign your own meaningful names to the fields and to their class.

record Amperage ( float idle , float busy ) {}
record Affix ( String prefix , String suffix ) {}
record Point ( int x , int y ) {}
record Rectangle ( Point p1 , Point p2 ) {}
record DateRange ( LocalDate start , LocalDate stop ) {}  // Or use `org.threeten.extra.LocalDateRange`. 

A record is appropriate where the main purpose of the class is to transparently communicate shallowly-immutable data.

The compiler implicitly creates an implementation of a constructor, getters,equals & hashCode, and toString.

Upvotes: 5

Related Questions